diff --git a/.changeset/blue-phones-rest.md b/.changeset/blue-phones-rest.md new file mode 100644 index 0000000000..4a427c7835 --- /dev/null +++ b/.changeset/blue-phones-rest.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Use audited version of OCR2Base.sol in OCR3Capability.sol diff --git a/.changeset/chilled-panthers-joke.md b/.changeset/chilled-panthers-joke.md new file mode 100644 index 0000000000..77dc481771 --- /dev/null +++ b/.changeset/chilled-panthers-joke.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal bump `chainlink-common` version to commit 6d926be950a6f6ca289a84edad938d4eef2ee337. diff --git a/.changeset/eleven-buckets-search.md b/.changeset/eleven-buckets-search.md new file mode 100644 index 0000000000..6c68fbcfdc --- /dev/null +++ b/.changeset/eleven-buckets-search.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Add Log Poller support to Chain Reader through setting them in config. All filters should be part of the contract wide filter unless an event needs specific polling configuration, which can be set on a per event basis.. diff --git a/.changeset/fair-buttons-judge.md b/.changeset/fair-buttons-judge.md new file mode 100644 index 0000000000..7aacd89787 --- /dev/null +++ b/.changeset/fair-buttons-judge.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Bumped `chainlink-common` package version to commit `1fb0b48758af25d689b6957ebfb76598c9fb27ea`. diff --git a/.changeset/funny-snails-shake.md b/.changeset/funny-snails-shake.md new file mode 100644 index 0000000000..dad6c90872 --- /dev/null +++ b/.changeset/funny-snails-shake.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Added API for products to query a transaction's status in the TXM #internal diff --git a/.changeset/fuzzy-frogs-live.md b/.changeset/fuzzy-frogs-live.md new file mode 100644 index 0000000000..58a9ffd228 --- /dev/null +++ b/.changeset/fuzzy-frogs-live.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added EVM implementation of GetFeeComponents function for ChainWriter diff --git a/.changeset/giant-pumpkins-return.md b/.changeset/giant-pumpkins-return.md new file mode 100644 index 0000000000..c908db198f --- /dev/null +++ b/.changeset/giant-pumpkins-return.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal bumped chainlink-common version to commit 1eff5dedc9857ed8811186dd2996603942dc1107 diff --git a/.changeset/healthy-plants-guess.md b/.changeset/healthy-plants-guess.md new file mode 100644 index 0000000000..6ec74b5a04 --- /dev/null +++ b/.changeset/healthy-plants-guess.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal removed HistoryDepth to FinalityDepth validation diff --git a/.changeset/lemon-buttons-raise.md b/.changeset/lemon-buttons-raise.md new file mode 100644 index 0000000000..0408383bd0 --- /dev/null +++ b/.changeset/lemon-buttons-raise.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/.changeset/metal-cars-report.md b/.changeset/metal-cars-report.md new file mode 100644 index 0000000000..a3667ed20e --- /dev/null +++ b/.changeset/metal-cars-report.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Bump to start the next version diff --git a/.changeset/metal-glasses-count.md b/.changeset/metal-glasses-count.md new file mode 100644 index 0000000000..0408383bd0 --- /dev/null +++ b/.changeset/metal-glasses-count.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/.changeset/ninety-zebras-hammer.md b/.changeset/ninety-zebras-hammer.md new file mode 100644 index 0000000000..0408383bd0 --- /dev/null +++ b/.changeset/ninety-zebras-hammer.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/.changeset/pink-ants-reply.md b/.changeset/pink-ants-reply.md new file mode 100644 index 0000000000..fab4ef31f7 --- /dev/null +++ b/.changeset/pink-ants-reply.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal remove shared secret from transmission schedule diff --git a/.changeset/pretty-dancers-pull.md b/.changeset/pretty-dancers-pull.md new file mode 100644 index 0000000000..af8ec9db0c --- /dev/null +++ b/.changeset/pretty-dancers-pull.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#changed Expand EVM implementation compatibility pipeline diff --git a/.changeset/rare-carpets-cry.md b/.changeset/rare-carpets-cry.md new file mode 100644 index 0000000000..f096d31885 --- /dev/null +++ b/.changeset/rare-carpets-cry.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal capability dispatcher threading and context usage diff --git a/.changeset/rotten-emus-work.md b/.changeset/rotten-emus-work.md new file mode 100644 index 0000000000..ecf5ee0b9f --- /dev/null +++ b/.changeset/rotten-emus-work.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal fixed a bug where we weren't sending the value param to the txm diff --git a/.changeset/shaggy-ears-share.md b/.changeset/shaggy-ears-share.md new file mode 100644 index 0000000000..5946faf03c --- /dev/null +++ b/.changeset/shaggy-ears-share.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Add RegistrySyncer diff --git a/.changeset/shiny-poems-juggle.md b/.changeset/shiny-poems-juggle.md new file mode 100644 index 0000000000..32fc2069ee --- /dev/null +++ b/.changeset/shiny-poems-juggle.md @@ -0,0 +1,6 @@ +--- +"chainlink": minor +--- + +#changed Refactored the BlockHistoryEstimator check to prevent excessively bumping transactions. Check no longer waits for CheckInclusionBlocks to pass before assessing an attempt. +#bugfix Fixed a bug that would use the oldest blocks in the cached history instead of the latest to perform gas estimations. diff --git a/.changeset/shy-deers-hope.md b/.changeset/shy-deers-hope.md new file mode 100644 index 0000000000..0408383bd0 --- /dev/null +++ b/.changeset/shy-deers-hope.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/.changeset/sour-pigs-develop.md b/.changeset/sour-pigs-develop.md new file mode 100644 index 0000000000..5737b20601 --- /dev/null +++ b/.changeset/sour-pigs-develop.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal remote target wait until initiated threads exit on close diff --git a/.changeset/stupid-poems-glow.md b/.changeset/stupid-poems-glow.md new file mode 100644 index 0000000000..bdd8acc66d --- /dev/null +++ b/.changeset/stupid-poems-glow.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal rework operator_ui installer diff --git a/.changeset/tall-walls-agree.md b/.changeset/tall-walls-agree.md new file mode 100644 index 0000000000..6f1f5505b6 --- /dev/null +++ b/.changeset/tall-walls-agree.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal upgrade keystone contracts to 0.8.24 diff --git a/.changeset/ten-falcons-suffer.md b/.changeset/ten-falcons-suffer.md new file mode 100644 index 0000000000..e4476b1045 --- /dev/null +++ b/.changeset/ten-falcons-suffer.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +move v23 contracts #bugfix diff --git a/.changeset/thick-lemons-beam.md b/.changeset/thick-lemons-beam.md new file mode 100644 index 0000000000..0ce6e04780 --- /dev/null +++ b/.changeset/thick-lemons-beam.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Add script to provision capability registry diff --git a/.changeset/thick-moles-travel.md b/.changeset/thick-moles-travel.md new file mode 100644 index 0000000000..45559e4715 --- /dev/null +++ b/.changeset/thick-moles-travel.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal moves workflow name and owner to the yaml spec diff --git a/.changeset/tiny-camels-flow.md b/.changeset/tiny-camels-flow.md new file mode 100644 index 0000000000..3271bbb4a3 --- /dev/null +++ b/.changeset/tiny-camels-flow.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix fixed ureachable code bug which could result in stuck txns diff --git a/.changeset/unlucky-pillows-fly.md b/.changeset/unlucky-pillows-fly.md new file mode 100644 index 0000000000..c8f690eda1 --- /dev/null +++ b/.changeset/unlucky-pillows-fly.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +add events, add getter and add comments #bugfix diff --git a/.changeset/warm-cobras-poke.md b/.changeset/warm-cobras-poke.md new file mode 100644 index 0000000000..0bfb1dd44b --- /dev/null +++ b/.changeset/warm-cobras-poke.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated Fix verb formatting in the log outputs. diff --git a/.changeset/wise-wasps-drum.md b/.changeset/wise-wasps-drum.md new file mode 100644 index 0000000000..0a4a6eaf66 --- /dev/null +++ b/.changeset/wise-wasps-drum.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Add loggercheck linter to verify that \*w logging methods have even number of args. diff --git a/.github/actions/build-chainlink-image/action.yml b/.github/actions/build-chainlink-image/action.yml index 733c56cf0f..c0d00d27e7 100644 --- a/.github/actions/build-chainlink-image/action.yml +++ b/.github/actions/build-chainlink-image/action.yml @@ -18,12 +18,16 @@ inputs: dep_evm_sha: description: The chainlink-evm commit sha to use in go deps required: false + check_image_exists: + description: "Check if the image exists in ECR before building" + required: false + default: 'false' runs: using: composite steps: - name: Check if image exists - if: ${{ inputs.dep_evm_sha != '' }} + if: ${{ inputs.dep_evm_sha != '' || inputs.check_image_exists == 'true'}} id: check-image uses: smartcontractkit/chainlink-github-actions/docker/image-exists@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 with: diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml index 0c1ba1e082..da436d9ec0 100644 --- a/.github/actions/build-test-image/action.yml +++ b/.github/actions/build-test-image/action.yml @@ -73,7 +73,7 @@ runs: id: check-base-image uses: smartcontractkit/chainlink-github-actions/docker/image-exists@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 with: - repository: ${{ inputs.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ inputs.QA_AWS_REGION }}.amazonaws.com/test-base-image + repository: test-base-image tag: ${{ steps.long_sha.outputs.long_sha }} AWS_REGION: ${{ inputs.QA_AWS_REGION }} AWS_ROLE_TO_ASSUME: ${{ inputs.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/actions/delete-deployments/action.yml b/.github/actions/delete-deployments/action.yml index 6641b352b3..eaf7e0f61b 100644 --- a/.github/actions/delete-deployments/action.yml +++ b/.github/actions/delete-deployments/action.yml @@ -31,7 +31,7 @@ runs: steps: - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 with: - version: ^8.0.0 + version: ^9.0.0 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: diff --git a/.github/actions/delete-deployments/package.json b/.github/actions/delete-deployments/package.json index d385569b2e..a2d6f83908 100644 --- a/.github/actions/delete-deployments/package.json +++ b/.github/actions/delete-deployments/package.json @@ -10,6 +10,10 @@ "keywords": [], "author": "", "license": "ISC", + "engines": { + "node": ">=18", + "pnpm": ">=9" + }, "dependencies": { "@actions/core": "^1.10.1", "@octokit/action": "^6.1.0", diff --git a/.github/actions/delete-deployments/pnpm-lock.yaml b/.github/actions/delete-deployments/pnpm-lock.yaml index 92da36617d..d9f25b3f80 100644 --- a/.github/actions/delete-deployments/pnpm-lock.yaml +++ b/.github/actions/delete-deployments/pnpm-lock.yaml @@ -1,285 +1,183 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@actions/core': - specifier: ^1.10.1 - version: 1.10.1 - '@octokit/action': - specifier: ^6.1.0 - version: 6.1.0 - '@octokit/plugin-retry': - specifier: ^6.0.1 - version: 6.0.1(@octokit/core@5.0.0) - '@octokit/plugin-throttling': - specifier: ^7.0.0 - version: 7.0.0(@octokit/core@5.0.0) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.10)(typescript@5.4.5) - -devDependencies: - '@octokit/types': - specifier: ^11.1.0 - version: 11.1.0 - '@types/node': - specifier: ^20.12.10 - version: 20.12.10 - typescript: - specifier: ^5.4.5 - version: 5.4.5 +importers: + + .: + dependencies: + '@actions/core': + specifier: ^1.10.1 + version: 1.10.1 + '@octokit/action': + specifier: ^6.1.0 + version: 6.1.0 + '@octokit/plugin-retry': + specifier: ^6.0.1 + version: 6.0.1(@octokit/core@5.0.0) + '@octokit/plugin-throttling': + specifier: ^7.0.0 + version: 7.0.0(@octokit/core@5.0.0) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.12.10)(typescript@5.4.5) + devDependencies: + '@octokit/types': + specifier: ^11.1.0 + version: 11.1.0 + '@types/node': + specifier: ^20.12.10 + version: 20.12.10 + typescript: + specifier: ^5.4.5 + version: 5.4.5 packages: - /@actions/core@1.10.1: + '@actions/core@1.10.1': resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} - dependencies: - '@actions/http-client': 2.1.1 - uuid: 8.3.2 - dev: false - /@actions/http-client@2.1.1: + '@actions/http-client@2.1.1': resolution: {integrity: sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw==} - dependencies: - tunnel: 0.0.6 - dev: false - /@cspotcode/source-map-support@0.8.1: + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: false - /@jridgewell/resolve-uri@3.1.1: + '@jridgewell/resolve-uri@3.1.1': resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} - dev: false - /@jridgewell/sourcemap-codec@1.4.15: + '@jridgewell/sourcemap-codec@1.4.15': resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: false - /@jridgewell/trace-mapping@0.3.9: + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: false - /@octokit/action@6.1.0: + '@octokit/action@6.1.0': resolution: {integrity: sha512-lo+nHx8kAV86bxvOVOI3vFjX3gXPd/L7guAUbvs3pUvnR2KC+R7yjBkA1uACt4gYhs4LcWP3AXSGQzsbeN2XXw==} engines: {node: '>= 18'} - dependencies: - '@octokit/auth-action': 4.0.0 - '@octokit/core': 5.0.0 - '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.0.0) - '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.0.0) - '@octokit/types': 12.6.0 - undici: 6.16.0 - dev: false - /@octokit/auth-action@4.0.0: + '@octokit/auth-action@4.0.0': resolution: {integrity: sha512-sMm9lWZdiX6e89YFaLrgE9EFs94k58BwIkvjOtozNWUqyTmsrnWFr/M5LolaRzZ7Kmb5FbhF9hi7FEeE274SoQ==} engines: {node: '>= 18'} - dependencies: - '@octokit/auth-token': 4.0.0 - '@octokit/types': 11.1.0 - dev: false - /@octokit/auth-token@4.0.0: + '@octokit/auth-token@4.0.0': resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} engines: {node: '>= 18'} - dev: false - /@octokit/core@5.0.0: + '@octokit/core@5.0.0': resolution: {integrity: sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==} engines: {node: '>= 18'} - dependencies: - '@octokit/auth-token': 4.0.0 - '@octokit/graphql': 7.0.1 - '@octokit/request': 8.1.1 - '@octokit/request-error': 5.0.0 - '@octokit/types': 11.1.0 - before-after-hook: 2.2.3 - universal-user-agent: 6.0.0 - dev: false - /@octokit/endpoint@9.0.0: + '@octokit/endpoint@9.0.0': resolution: {integrity: sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==} engines: {node: '>= 18'} - dependencies: - '@octokit/types': 11.1.0 - is-plain-object: 5.0.0 - universal-user-agent: 6.0.0 - dev: false - /@octokit/graphql@7.0.1: + '@octokit/graphql@7.0.1': resolution: {integrity: sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==} engines: {node: '>= 18'} - dependencies: - '@octokit/request': 8.1.1 - '@octokit/types': 11.1.0 - universal-user-agent: 6.0.0 - dev: false - /@octokit/openapi-types@18.0.0: + '@octokit/openapi-types@18.0.0': resolution: {integrity: sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==} - /@octokit/openapi-types@20.0.0: + '@octokit/openapi-types@20.0.0': resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} - dev: false - /@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.0.0): + '@octokit/plugin-paginate-rest@9.2.1': resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' - dependencies: - '@octokit/core': 5.0.0 - '@octokit/types': 12.6.0 - dev: false - /@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.0.0): + '@octokit/plugin-rest-endpoint-methods@10.4.1': resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' - dependencies: - '@octokit/core': 5.0.0 - '@octokit/types': 12.6.0 - dev: false - /@octokit/plugin-retry@6.0.1(@octokit/core@5.0.0): + '@octokit/plugin-retry@6.0.1': resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=5' - dependencies: - '@octokit/core': 5.0.0 - '@octokit/request-error': 5.0.0 - '@octokit/types': 12.6.0 - bottleneck: 2.19.5 - dev: false - /@octokit/plugin-throttling@7.0.0(@octokit/core@5.0.0): + '@octokit/plugin-throttling@7.0.0': resolution: {integrity: sha512-KL2k/d0uANc8XqP5S64YcNFCudR3F5AaKO39XWdUtlJIjT9Ni79ekWJ6Kj5xvAw87udkOMEPcVf9xEge2+ahew==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': ^5.0.0 - dependencies: - '@octokit/core': 5.0.0 - '@octokit/types': 11.1.0 - bottleneck: 2.19.5 - dev: false - /@octokit/request-error@5.0.0: + '@octokit/request-error@5.0.0': resolution: {integrity: sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==} engines: {node: '>= 18'} - dependencies: - '@octokit/types': 11.1.0 - deprecation: 2.3.1 - once: 1.4.0 - dev: false - /@octokit/request@8.1.1: + '@octokit/request@8.1.1': resolution: {integrity: sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==} engines: {node: '>= 18'} - dependencies: - '@octokit/endpoint': 9.0.0 - '@octokit/request-error': 5.0.0 - '@octokit/types': 11.1.0 - is-plain-object: 5.0.0 - universal-user-agent: 6.0.0 - dev: false - /@octokit/types@11.1.0: + '@octokit/types@11.1.0': resolution: {integrity: sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==} - dependencies: - '@octokit/openapi-types': 18.0.0 - /@octokit/types@12.6.0: + '@octokit/types@12.6.0': resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} - dependencies: - '@octokit/openapi-types': 20.0.0 - dev: false - /@tsconfig/node10@1.0.9: + '@tsconfig/node10@1.0.9': resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: false - /@tsconfig/node12@1.0.11: + '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: false - /@tsconfig/node14@1.0.3: + '@tsconfig/node14@1.0.3': resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: false - /@tsconfig/node16@1.0.4: + '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: false - /@types/node@20.12.10: + '@types/node@20.12.10': resolution: {integrity: sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==} - dependencies: - undici-types: 5.26.5 - /acorn-walk@8.2.0: + acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} - dev: false - /acorn@8.10.0: + acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} hasBin: true - dev: false - /arg@4.1.3: + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: false - /before-after-hook@2.2.3: + before-after-hook@2.2.3: resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - dev: false - /bottleneck@2.19.5: + bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - dev: false - /create-require@1.1.1: + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: false - /deprecation@2.3.1: + deprecation@2.3.1: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} - dev: false - /diff@4.0.2: + diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dev: false - /is-plain-object@5.0.0: + is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} - dev: false - /make-error@1.3.6: + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: false - /once@1.4.0: + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: false - /ts-node@10.9.2(@types/node@20.12.10)(typescript@5.4.5): + ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: @@ -292,6 +190,188 @@ packages: optional: true '@swc/wasm': optional: true + + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@6.16.0: + resolution: {integrity: sha512-HQfVddOTb5PJtfLnJ1Px8bNGyIg/z7WTj1hjUSna1Itsv59Oca9JdclIU08ToNqvWWXjFLRzc9rqjnpfw5UWcQ==} + engines: {node: '>=18.17'} + + universal-user-agent@6.0.0: + resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + +snapshots: + + '@actions/core@1.10.1': + dependencies: + '@actions/http-client': 2.1.1 + uuid: 8.3.2 + + '@actions/http-client@2.1.1': + dependencies: + tunnel: 0.0.6 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@jridgewell/resolve-uri@3.1.1': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@octokit/action@6.1.0': + dependencies: + '@octokit/auth-action': 4.0.0 + '@octokit/core': 5.0.0 + '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.0.0) + '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.0.0) + '@octokit/types': 12.6.0 + undici: 6.16.0 + + '@octokit/auth-action@4.0.0': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/types': 11.1.0 + + '@octokit/auth-token@4.0.0': {} + + '@octokit/core@5.0.0': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.0.1 + '@octokit/request': 8.1.1 + '@octokit/request-error': 5.0.0 + '@octokit/types': 11.1.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.0 + + '@octokit/endpoint@9.0.0': + dependencies: + '@octokit/types': 11.1.0 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + + '@octokit/graphql@7.0.1': + dependencies: + '@octokit/request': 8.1.1 + '@octokit/types': 11.1.0 + universal-user-agent: 6.0.0 + + '@octokit/openapi-types@18.0.0': {} + + '@octokit/openapi-types@20.0.0': {} + + '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.0.0)': + dependencies: + '@octokit/core': 5.0.0 + '@octokit/types': 12.6.0 + + '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.0.0)': + dependencies: + '@octokit/core': 5.0.0 + '@octokit/types': 12.6.0 + + '@octokit/plugin-retry@6.0.1(@octokit/core@5.0.0)': + dependencies: + '@octokit/core': 5.0.0 + '@octokit/request-error': 5.0.0 + '@octokit/types': 12.6.0 + bottleneck: 2.19.5 + + '@octokit/plugin-throttling@7.0.0(@octokit/core@5.0.0)': + dependencies: + '@octokit/core': 5.0.0 + '@octokit/types': 11.1.0 + bottleneck: 2.19.5 + + '@octokit/request-error@5.0.0': + dependencies: + '@octokit/types': 11.1.0 + deprecation: 2.3.1 + once: 1.4.0 + + '@octokit/request@8.1.1': + dependencies: + '@octokit/endpoint': 9.0.0 + '@octokit/request-error': 5.0.0 + '@octokit/types': 11.1.0 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + + '@octokit/types@11.1.0': + dependencies: + '@octokit/openapi-types': 18.0.0 + + '@octokit/types@12.6.0': + dependencies: + '@octokit/openapi-types': 20.0.0 + + '@tsconfig/node10@1.0.9': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/node@20.12.10': + dependencies: + undici-types: 5.26.5 + + acorn-walk@8.2.0: {} + + acorn@8.10.0: {} + + arg@4.1.3: {} + + before-after-hook@2.2.3: {} + + bottleneck@2.19.5: {} + + create-require@1.1.1: {} + + deprecation@2.3.1: {} + + diff@4.0.2: {} + + is-plain-object@5.0.0: {} + + make-error@1.3.6: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + ts-node@10.9.2(@types/node@20.12.10)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 @@ -308,44 +388,21 @@ packages: typescript: 5.4.5 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: false - /tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - dev: false + tunnel@0.0.6: {} - /typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} - engines: {node: '>=14.17'} - hasBin: true + typescript@5.4.5: {} - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@5.26.5: {} - /undici@6.16.0: - resolution: {integrity: sha512-HQfVddOTb5PJtfLnJ1Px8bNGyIg/z7WTj1hjUSna1Itsv59Oca9JdclIU08ToNqvWWXjFLRzc9rqjnpfw5UWcQ==} - engines: {node: '>=18.17'} - dev: false + undici@6.16.0: {} - /universal-user-agent@6.0.0: - resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} - dev: false + universal-user-agent@6.0.0: {} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false + uuid@8.3.2: {} - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: false + v8-compile-cache-lib@3.0.1: {} - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false + wrappy@1.0.2: {} - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: false + yn@3.1.1: {} diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index d3758bca9e..f3697ed719 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -53,7 +53,7 @@ runs: - name: golangci-lint uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 with: - version: v1.55.2 + version: v1.59.1 # We already cache these directories in setup-go skip-pkg-cache: true skip-build-cache: true diff --git a/.github/actions/notify-slack-jobs-result/action.yml b/.github/actions/notify-slack-jobs-result/action.yml index f5df87bb90..da7daa5b62 100644 --- a/.github/actions/notify-slack-jobs-result/action.yml +++ b/.github/actions/notify-slack-jobs-result/action.yml @@ -25,6 +25,9 @@ inputs: slack_thread_ts: description: "The Slack thread timestamp to post the message to, handy for keeping multiple related results in a single thread" required: false + base64_parsed_results: + description: "Base64 encoded parsed results to use" + required: false runs: using: composite @@ -33,43 +36,54 @@ runs: shell: bash id: test-results run: | - # I feel like there's some clever, fully jq way to do this, but I ain't got the motivation to figure it out - echo "Querying test results at https://api.github.com/repos/${{inputs.github_repository}}/actions/runs/${{ inputs.workflow_run_id }}/jobs" - - # we can get a maximum of 100 jobs per page, after that we need to start using pagination - PARSED_RESULTS=$(curl \ - -H "Authorization: Bearer ${{ inputs.github_token }}" \ - 'https://api.github.com/repos/${{inputs.github_repository}}/actions/runs/${{ inputs.workflow_run_id }}/jobs?per_page=100' \ - | jq -r --arg pattern "${{ inputs.github_job_name_regex }}" '.jobs[] - | select(.name | test($pattern)) as $job - | $job.steps[] - | select(.name == "Run Tests") - | { conclusion: (if .conclusion == "success" then ":white_check_mark:" else ":x:" end), cap: ("*" + ($job.name | capture($pattern).cap) + "*"), html_url: $job.html_url }') - + if [ -n "${{ inputs.base64_parsed_results }}" ]; then + echo "Using base64 parsed results" + PARSED_RESULTS=$(echo "${{ inputs.base64_parsed_results }}" | base64 -d) + else + go install github.com/smartcontractkit/chainlink-testing-framework/tools/workflowresultparser@v1.0.0 + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + workflowresultparser -workflowRunID ${{ inputs.workflow_run_id }} -githubToken ${{ inputs.github_token }} -githubRepo "${{ inputs.github_repository }}" -jobNameRegex "${{ inputs.github_job_name_regex }}" -outputFile=output.json + + if [ ! -f output.json ]; then + PARSED_RESULTS='""' + else + PARSED_RESULTS=$(cat output.json | jq -c "select(has(\"results\")) | .results[]") + fi + + fi + echo "Parsed Results:" echo $PARSED_RESULTS - + ALL_SUCCESS=true - echo "Checking for failures" - echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")' - for row in $(echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")'); do - ALL_SUCCESS=false - break - done - echo "Success: $ALL_SUCCESS" - - echo all_success=$ALL_SUCCESS >> $GITHUB_OUTPUT - - FORMATTED_RESULTS=$(echo $PARSED_RESULTS | jq -s '[.[] - | { - conclusion: .conclusion, - cap: .cap, - html_url: .html_url - } - ] - | map("{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"<\(.html_url)|\(.cap)>: \(.conclusion)\"}}") - | join(",")') - + + if [ "$PARSED_RESULTS" != '""' ]; then + echo "Checking for failures" + echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")' + for row in $(echo "$PARSED_RESULTS" | jq -s | jq -r '.[] | select(.conclusion != ":white_check_mark:")'); do + ALL_SUCCESS=false + break + done + echo "Success: $ALL_SUCCESS" + + echo all_success=$ALL_SUCCESS >> $GITHUB_OUTPUT + + FORMATTED_RESULTS=$(echo $PARSED_RESULTS | jq -s '[.[] + | { + conclusion: .conclusion, + cap: .cap, + html_url: .html_url + } + ] + | map("{\"type\": \"section\", \"text\": {\"type\": \"mrkdwn\", \"text\": \"<\(.html_url)|\(.cap)>: \(.conclusion)\"}}") + | join(",")') + else + echo "Nothing to post, no results found" + exit 0 + fi + echo "Formatted Results:" echo $FORMATTED_RESULTS @@ -82,6 +96,7 @@ runs: echo results=$CLEAN_RESULTS >> $GITHUB_OUTPUT - name: Post Results uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + if: steps.test-results.outputs.results != '' env: SLACK_BOT_TOKEN: ${{ inputs.slack_bot_token }} with: @@ -108,4 +123,4 @@ runs: ] } ] - } + } diff --git a/.github/actions/setup-nodejs/action.yaml b/.github/actions/setup-nodejs/action.yaml index ae6975e741..9dc1cf375d 100644 --- a/.github/actions/setup-nodejs/action.yaml +++ b/.github/actions/setup-nodejs/action.yaml @@ -9,7 +9,7 @@ runs: steps: - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 with: - version: ^7.0.0 + version: ^9.0.0 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: diff --git a/.github/actions/split-tests/action.yaml b/.github/actions/split-tests/action.yaml index 633e897db5..d11f0bcbc3 100644 --- a/.github/actions/split-tests/action.yaml +++ b/.github/actions/split-tests/action.yaml @@ -13,7 +13,7 @@ runs: steps: - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 with: - version: ^7.0.0 + version: ^8.0.0 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: diff --git a/.github/actions/split-tests/package.json b/.github/actions/split-tests/package.json index cddc547bb1..10a71c0b35 100644 --- a/.github/actions/split-tests/package.json +++ b/.github/actions/split-tests/package.json @@ -11,6 +11,10 @@ "keywords": [], "author": "", "license": "MIT", + "engines": { + "node": "^16.0.0", + "pnpm": "^8.0.0" + }, "dependencies": { "@actions/core": "^1.10.1", "ts-node": "^10.9.2", diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f9b33ef456..e77921d0dd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ ## Motivation -## Solution \ No newline at end of file +## Solution diff --git a/.github/scripts/crib/package.json b/.github/scripts/crib/package.json index 8a935ecae3..b009d63f38 100644 --- a/.github/scripts/crib/package.json +++ b/.github/scripts/crib/package.json @@ -7,6 +7,10 @@ "keywords": [], "author": "", "license": "MIT", + "engines": { + "node": ">=18", + "pnpm": ">=9" + }, "dependencies": { "@actions/core": "^1.10.1", "@actions/github": "^6.0.0", diff --git a/.github/scripts/crib/pnpm-lock.yaml b/.github/scripts/crib/pnpm-lock.yaml index c449716078..a65caf8355 100644 --- a/.github/scripts/crib/pnpm-lock.yaml +++ b/.github/scripts/crib/pnpm-lock.yaml @@ -1,64 +1,454 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@actions/core': - specifier: ^1.10.1 - version: 1.10.1 - '@actions/github': - specifier: ^6.0.0 - version: 6.0.0 - '@aws-sdk/client-route-53': - specifier: ^3.525.0 - version: 3.529.1 - '@octokit/rest': - specifier: ^20.0.2 - version: 20.0.2 +importers: + + .: + dependencies: + '@actions/core': + specifier: ^1.10.1 + version: 1.10.1 + '@actions/github': + specifier: ^6.0.0 + version: 6.0.0 + '@aws-sdk/client-route-53': + specifier: ^3.525.0 + version: 3.529.1 + '@octokit/rest': + specifier: ^20.0.2 + version: 20.0.2 packages: - /@actions/core@1.10.1: + '@actions/core@1.10.1': resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} + + '@actions/github@6.0.0': + resolution: {integrity: sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==} + + '@actions/http-client@2.2.1': + resolution: {integrity: sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==} + + '@aws-crypto/crc32@3.0.0': + resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + + '@aws-crypto/ie11-detection@3.0.0': + resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==} + + '@aws-crypto/sha256-browser@3.0.0': + resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==} + + '@aws-crypto/sha256-js@3.0.0': + resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} + + '@aws-crypto/supports-web-crypto@3.0.0': + resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==} + + '@aws-crypto/util@3.0.0': + resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + + '@aws-sdk/client-route-53@3.529.1': + resolution: {integrity: sha512-osra30V5ILwEBeE1DUZreY7HYWQGco+WcQ1qg1UDSh/C0Nyxlu+8bVpwB/bjaldmy5Fi9MRv8SQsMdiAJFNp+w==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/client-sso-oidc@3.529.1': + resolution: {integrity: sha512-bimxCWAvRnVcluWEQeadXvHyzWlBWsuGVligsaVZaGF0TLSn0eLpzpN9B1EhHzTf7m0Kh/wGtPSH1JxO6PpB+A==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@aws-sdk/credential-provider-node': ^3.529.1 + + '@aws-sdk/client-sso@3.529.1': + resolution: {integrity: sha512-KT1U/ZNjDhVv2ZgjzaeAn9VM7l667yeSguMrRYC8qk5h91/61MbjZypi6eOuKuVM+0fsQvzKScTQz0Lio0eYag==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/client-sts@3.529.1': + resolution: {integrity: sha512-Rvk2Sr3MACQTOtngUU+omlf4E17k47dRVXR7OFRD6Ow5iGgC9tkN2q/ExDPW/ktPOmM0lSgzWyQ6/PC/Zq3HUg==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@aws-sdk/credential-provider-node': ^3.529.1 + + '@aws-sdk/core@3.529.1': + resolution: {integrity: sha512-Sj42sYPfaL9PHvvciMICxhyrDZjqnnvFbPKDmQL5aFKyXy122qx7RdVqUOQERDmMQfvJh6+0W1zQlLnre89q4Q==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-env@3.523.0': + resolution: {integrity: sha512-Y6DWdH6/OuMDoNKVzZlNeBc6f1Yjk1lYMjANKpIhMbkRCvLJw/PYZKOZa8WpXbTYdgg9XLjKybnLIb3ww3uuzA==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-http@3.525.0': + resolution: {integrity: sha512-RNWQGuSBQZhl3iqklOslUEfQ4br1V3DCPboMpeqFtddUWJV3m2u2extFur9/4Uy+1EHVF120IwZUKtd8dF+ibw==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-ini@3.529.1': + resolution: {integrity: sha512-RjHsuTvHIwXG7a/3ERexemiD3c9riKMCZQzY2/b0Gg0ButEVbBcMfERtUzWmQ0V4ufe/PEZjP68MH1gupcoF9A==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-node@3.529.1': + resolution: {integrity: sha512-mvY7F3dMmk/0dZOCfl5sUI1bG0osureBjxhELGCF0KkJqhWI0hIzh8UnPkYytSg3vdc97CMv7pTcozxrdA3b0g==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-process@3.523.0': + resolution: {integrity: sha512-f0LP9KlFmMvPWdKeUKYlZ6FkQAECUeZMmISsv6NKtvPCI9e4O4cLTeR09telwDK8P0HrgcRuZfXM7E30m8re0Q==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-sso@3.529.1': + resolution: {integrity: sha512-KFMKkaoTGDgSJG+o9Ii7AglWG5JQeF6IFw9cXLMwDdIrp3KUmRcUIqe0cjOoCqeQEDGy0VHsimHmKKJ3894i/A==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.529.1': + resolution: {integrity: sha512-AGuZDOKN+AttjwTjrF47WLqzeEut2YynyxjkXZhxZF/xn8i5Y51kUAUdXsXw1bgR25pAeXQIdhsrQlRa1Pm5kw==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/middleware-host-header@3.523.0': + resolution: {integrity: sha512-4g3q7Ta9sdD9TMUuohBAkbx/e3I/juTqfKi7TPgP+8jxcYX72MOsgemAMHuP6CX27eyj4dpvjH+w4SIVDiDSmg==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/middleware-logger@3.523.0': + resolution: {integrity: sha512-PeDNJNhfiaZx54LBaLTXzUaJ9LXFwDFFIksipjqjvxMafnoVcQwKbkoPUWLe5ytT4nnL1LogD3s55mERFUsnwg==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.523.0': + resolution: {integrity: sha512-nZ3Vt7ehfSDYnrcg/aAfjjvpdE+61B3Zk68i6/hSUIegT3IH9H1vSW67NDKVp+50hcEfzWwM2HMPXxlzuyFyrw==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/middleware-sdk-route53@3.523.0': + resolution: {integrity: sha512-d+SKqDBM3XCVkF/crRWwJD1WuS4PBY/CaTGwIyND1Z3o3ZCMhyo4f2ni19U+7ZtEULW50ZGznhB2F4GJHqpDUg==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/middleware-user-agent@3.525.0': + resolution: {integrity: sha512-4al/6uO+t/QIYXK2OgqzDKQzzLAYJza1vWFS+S0lJ3jLNGyLB5BMU5KqWjDzevYZ4eCnz2Nn7z0FveUTNz8YdQ==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/region-config-resolver@3.525.0': + resolution: {integrity: sha512-8kFqXk6UyKgTMi7N7QlhA6qM4pGPWbiUXqEY2RgUWngtxqNFGeM9JTexZeuavQI+qLLe09VPShPNX71fEDcM6w==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/token-providers@3.529.1': + resolution: {integrity: sha512-NpgMjsfpqiugbxrYGXtta914N43Mx/H0niidqv8wKMTgWQEtsJvYtOni+kuLXB+LmpjaMFNlpadooFU/bK4buA==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/types@3.523.0': + resolution: {integrity: sha512-AqGIu4u+SxPiUuNBp2acCVcq80KDUFjxe6e3cMTvKWTzCbrVk1AXv0dAaJnCmdkWIha6zJDWxpIk/aL4EGhZ9A==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/util-endpoints@3.525.0': + resolution: {integrity: sha512-DIW7WWU5tIGkeeKX6NJUyrEIdWMiqjLQG3XBzaUj+ufIENwNjdAHhlD8l2vX7Yr3JZRT6yN/84wBCj7Tw1xd1g==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/util-locate-window@3.495.0': + resolution: {integrity: sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg==} + engines: {node: '>=14.0.0'} + + '@aws-sdk/util-user-agent-browser@3.523.0': + resolution: {integrity: sha512-6ZRNdGHX6+HQFqTbIA5+i8RWzxFyxsZv8D3soRfpdyWIKkzhSz8IyRKXRciwKBJDaC7OX2jzGE90wxRQft27nA==} + + '@aws-sdk/util-user-agent-node@3.525.0': + resolution: {integrity: sha512-88Wjt4efyUSBGcyIuh1dvoMqY1k15jpJc5A/3yi67clBQEFsu9QCodQCQPqmRjV3VRcMtBOk+jeCTiUzTY5dRQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + + '@aws-sdk/xml-builder@3.523.0': + resolution: {integrity: sha512-wfvyVymj2TUw7SuDor9IuFcAzJZvWRBZotvY/wQJOlYa3UP3Oezzecy64N4FWfBJEsZdrTN+HOZFl+IzTWWnUA==} + engines: {node: '>=14.0.0'} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + + '@octokit/core@5.1.0': + resolution: {integrity: sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==} + engines: {node: '>= 18'} + + '@octokit/endpoint@9.0.4': + resolution: {integrity: sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==} + engines: {node: '>= 18'} + + '@octokit/graphql@7.0.2': + resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@20.0.0': + resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} + + '@octokit/plugin-paginate-rest@9.2.1': + resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-request-log@4.0.1': + resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-rest-endpoint-methods@10.4.1': + resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/request-error@5.0.1': + resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} + engines: {node: '>= 18'} + + '@octokit/request@8.2.0': + resolution: {integrity: sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==} + engines: {node: '>= 18'} + + '@octokit/rest@20.0.2': + resolution: {integrity: sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==} + engines: {node: '>= 18'} + + '@octokit/types@12.6.0': + resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} + + '@smithy/abort-controller@2.1.4': + resolution: {integrity: sha512-66HO817oIZ2otLIqy06R5muapqZjkgF1jfU0wyNko8cuqZNu8nbS9ljlhcRYw/M/uWRJzB9ih81DLSHhYbBLlQ==} + engines: {node: '>=14.0.0'} + + '@smithy/config-resolver@2.1.5': + resolution: {integrity: sha512-LcBB5JQC3Tx2ZExIJzfvWaajhFIwHrUNQeqxhred2r5nnqrdly9uoCrvM1sxOOdghYuWWm2Kr8tBCDOmxsgeTA==} + engines: {node: '>=14.0.0'} + + '@smithy/core@1.3.8': + resolution: {integrity: sha512-6cFhQ9ChU7MxvOXJn6nuUSONacpNsGHWhfueROQuM/0vibDdZA9FWEdNbVkuVuc+BFI5BnaX3ltERUlpUirpIA==} + engines: {node: '>=14.0.0'} + + '@smithy/credential-provider-imds@2.2.6': + resolution: {integrity: sha512-+xQe4Pite0kdk9qn0Vyw5BRVh0iSlj+T4TEKRXr4E1wZKtVgIzGlkCrfICSjiPVFkPxk4jMpVboMYdEiiA88/w==} + engines: {node: '>=14.0.0'} + + '@smithy/eventstream-codec@2.1.4': + resolution: {integrity: sha512-UkiieTztP7adg8EuqZvB0Y4LewdleZCJU7Kgt9RDutMsRYqO32fMpWeQHeTHaIMosmzcRZUykMRrhwGJe9mP3A==} + + '@smithy/fetch-http-handler@2.4.5': + resolution: {integrity: sha512-FR1IMGdo0yRFs1tk71zRGSa1MznVLQOVNaPjyNtx6dOcy/u0ovEnXN5NVz6slw5KujFlg3N1w4+UbO8F3WyYUg==} + + '@smithy/hash-node@2.1.4': + resolution: {integrity: sha512-uvCcpDLXaTTL0X/9ezF8T8sS77UglTfZVQaUOBiCvR0QydeSyio3t0Hj3QooVdyFsKTubR8gCk/ubLk3vAyDng==} + engines: {node: '>=14.0.0'} + + '@smithy/invalid-dependency@2.1.4': + resolution: {integrity: sha512-QzlNBl6jt3nb9jNnE51wTegReVvUdozyMMrFEyb/rc6AzPID1O+qMJYjAAoNw098y0CZVfCpEnoK2+mfBOd8XA==} + + '@smithy/is-array-buffer@2.1.1': + resolution: {integrity: sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==} + engines: {node: '>=14.0.0'} + + '@smithy/middleware-content-length@2.1.4': + resolution: {integrity: sha512-C6VRwfcr0w9qRFhDGCpWMVhlEIBFlmlPRP1aX9Cv9xDj9SUwlDrNvoV1oP1vjRYuLxCDgovBBynCwwcluS2wLw==} + engines: {node: '>=14.0.0'} + + '@smithy/middleware-endpoint@2.4.6': + resolution: {integrity: sha512-AsXtUXHPOAS0EGZUSFOsVJvc7p0KL29PGkLxLfycPOcFVLru/oinYB6yvyL73ZZPX2OB8sMYUMrj7eH2kI7V/w==} + engines: {node: '>=14.0.0'} + + '@smithy/middleware-retry@2.1.7': + resolution: {integrity: sha512-8fOP/cJN4oMv+5SRffZC8RkqfWxHqGgn/86JPINY/1DnTRegzf+G5GT9lmIdG1YasuSbU7LISfW9PXil3isPVw==} + engines: {node: '>=14.0.0'} + + '@smithy/middleware-serde@2.2.1': + resolution: {integrity: sha512-VAWRWqnNjgccebndpyK94om4ZTYzXLQxUmNCXYzM/3O9MTfQjTNBgtFtQwyIIez6z7LWcCsXmnKVIOE9mLqAHQ==} + engines: {node: '>=14.0.0'} + + '@smithy/middleware-stack@2.1.4': + resolution: {integrity: sha512-Qqs2ba8Ax1rGKOSGJS2JN23fhhox2WMdRuzx0NYHtXzhxbJOIMmz9uQY6Hf4PY8FPteBPp1+h0j5Fmr+oW12sg==} + engines: {node: '>=14.0.0'} + + '@smithy/node-config-provider@2.2.5': + resolution: {integrity: sha512-CxPf2CXhjO79IypHJLBATB66Dw6suvr1Yc2ccY39hpR6wdse3pZ3E8RF83SODiNH0Wjmkd0ze4OF8exugEixgA==} + engines: {node: '>=14.0.0'} + + '@smithy/node-http-handler@2.4.3': + resolution: {integrity: sha512-bD5zRdEl1u/4vAAMeQnGEUNbH1seISV2Z0Wnn7ltPRl/6B2zND1R9XzTfsOnH1R5jqghpochF/mma8u7uXz0qQ==} + engines: {node: '>=14.0.0'} + + '@smithy/property-provider@2.1.4': + resolution: {integrity: sha512-nWaY/MImj1BiXZ9WY65h45dcxOx8pl06KYoHxwojDxDL+Q9yLU1YnZpgv8zsHhEftlj9KhePENjQTlNowWVyug==} + engines: {node: '>=14.0.0'} + + '@smithy/protocol-http@3.2.2': + resolution: {integrity: sha512-xYBlllOQcOuLoxzhF2u8kRHhIFGQpDeTQj/dBSnw4kfI29WMKL5RnW1m9YjnJAJ49miuIvrkJR+gW5bCQ+Mchw==} + engines: {node: '>=14.0.0'} + + '@smithy/querystring-builder@2.1.4': + resolution: {integrity: sha512-LXSL0J/nRWvGT+jIj+Fip3j0J1ZmHkUyBFRzg/4SmPNCLeDrtVu7ptKOnTboPsFZu5BxmpYok3kJuQzzRdrhbw==} + engines: {node: '>=14.0.0'} + + '@smithy/querystring-parser@2.1.4': + resolution: {integrity: sha512-U2b8olKXgZAs0eRo7Op11jTNmmcC/sqYmsA7vN6A+jkGnDvJlEl7AetUegbBzU8q3D6WzC5rhR/joIy8tXPzIg==} + engines: {node: '>=14.0.0'} + + '@smithy/service-error-classification@2.1.4': + resolution: {integrity: sha512-JW2Hthy21evnvDmYYk1kItOmbp3X5XI5iqorXgFEunb6hQfSDZ7O1g0Clyxg7k/Pcr9pfLk5xDIR2To/IohlsQ==} + engines: {node: '>=14.0.0'} + + '@smithy/shared-ini-file-loader@2.3.5': + resolution: {integrity: sha512-oI99+hOvsM8oAJtxAGmoL/YCcGXtbP0fjPseYGaNmJ4X5xOFTer0KPk7AIH3AL6c5AlYErivEi1X/X78HgTVIw==} + engines: {node: '>=14.0.0'} + + '@smithy/signature-v4@2.1.4': + resolution: {integrity: sha512-gnu9gCn0qQ8IdhNjs6o3QVCXzUs33znSDYwVMWo3nX4dM6j7z9u6FC302ShYyVWfO4MkVMuGCCJ6nl3PcH7V1Q==} + engines: {node: '>=14.0.0'} + + '@smithy/smithy-client@2.4.5': + resolution: {integrity: sha512-igXOM4kPXPo6b5LZXTUqTnrGk20uVd8OXoybC3f89gczzGfziLK4yUNOmiHSdxY9OOMOnnhVe5MpTm01MpFqvA==} + engines: {node: '>=14.0.0'} + + '@smithy/types@2.11.0': + resolution: {integrity: sha512-AR0SXO7FuAskfNhyGfSTThpLRntDI5bOrU0xrpVYU0rZyjl3LBXInZFMTP/NNSd7IS6Ksdtar0QvnrPRIhVrLQ==} + engines: {node: '>=14.0.0'} + + '@smithy/url-parser@2.1.4': + resolution: {integrity: sha512-1hTy6UYRYqOZlHKH2/2NzdNQ4NNmW2Lp0sYYvztKy+dEQuLvZL9w88zCzFQqqFer3DMcscYOshImxkJTGdV+rg==} + + '@smithy/util-base64@2.2.1': + resolution: {integrity: sha512-troGfokrpoqv8TGgsb8p4vvM71vqor314514jyQ0i9Zae3qs0jUVbSMCIBB1tseVynXFRcZJAZ9hPQYlifLD5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-body-length-browser@2.1.1': + resolution: {integrity: sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==} + + '@smithy/util-body-length-node@2.2.2': + resolution: {integrity: sha512-U7DooaT1SfW7XHrOcxthYJnQ+WMaefRrFPxW5Qmypw38Ivv+TKvfVuVHA9V162h8BeW9rzOJwOunjgXd0DdB4w==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@2.1.1': + resolution: {integrity: sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==} + engines: {node: '>=14.0.0'} + + '@smithy/util-config-provider@2.2.1': + resolution: {integrity: sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==} + engines: {node: '>=14.0.0'} + + '@smithy/util-defaults-mode-browser@2.1.7': + resolution: {integrity: sha512-vvIpWsysEdY77R0Qzr6+LRW50ye7eii7AyHM0OJnTi0isHYiXo5M/7o4k8gjK/b1upQJdfjzSBoJVa2SWrI+2g==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-defaults-mode-node@2.2.7': + resolution: {integrity: sha512-qzXkSDyU6Th+rNNcNkG4a7Ix7m5HlMOtSCPxTVKlkz7eVsqbSSPggegbFeQJ2MVELBB4wnzNPsVPJIrpIaJpXA==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-endpoints@1.1.5': + resolution: {integrity: sha512-tgDpaUNsUtRvNiBulKU1VnpoXU1GINMfZZXunRhUXOTBEAufG1Wp79uDXLau2gg1RZ4dpAR6lXCkrmddihCGUg==} + engines: {node: '>= 14.0.0'} + + '@smithy/util-hex-encoding@2.1.1': + resolution: {integrity: sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==} + engines: {node: '>=14.0.0'} + + '@smithy/util-middleware@2.1.4': + resolution: {integrity: sha512-5yYNOgCN0DL0OplME0pthoUR/sCfipnROkbTO7m872o0GHCVNJj5xOFJ143rvHNA54+pIPMLum4z2DhPC2pVGA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-retry@2.1.4': + resolution: {integrity: sha512-JRZwhA3fhkdenSEYIWatC8oLwt4Bdf2LhHbNQApqb7yFoIGMl4twcYI3BcJZ7YIBZrACA9jGveW6tuCd836XzQ==} + engines: {node: '>= 14.0.0'} + + '@smithy/util-stream@2.1.5': + resolution: {integrity: sha512-FqvBFeTgx+QC4+i8USHqU8Ifs9nYRpW/OBfksojtgkxPIQ2H7ypXDEbnQRAV7PwoNHWcSwPomLYi0svmQQG5ow==} + engines: {node: '>=14.0.0'} + + '@smithy/util-uri-escape@2.1.1': + resolution: {integrity: sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@2.2.0': + resolution: {integrity: sha512-hBsKr5BqrDrKS8qy+YcV7/htmMGxriA1PREOf/8AGBhHIZnfilVv1Waf1OyKhSbFW15U/8+gcMUQ9/Kk5qwpHQ==} + engines: {node: '>=14.0.0'} + + '@smithy/util-waiter@2.1.4': + resolution: {integrity: sha512-AK17WaC0hx1wR9juAOsQkJ6DjDxBGEf5TrKhpXtNFEn+cVto9Li3MVsdpAO97AF7bhFXSyC8tJA3F4ThhqwCdg==} + engines: {node: '>=14.0.0'} + + before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + + bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + + deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + + fast-xml-parser@4.2.5: + resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} + hasBin: true + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + + undici@5.28.3: + resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==} + engines: {node: '>=14.0'} + + universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + +snapshots: + + '@actions/core@1.10.1': dependencies: '@actions/http-client': 2.2.1 uuid: 8.3.2 - dev: false - /@actions/github@6.0.0: - resolution: {integrity: sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==} + '@actions/github@6.0.0': dependencies: '@actions/http-client': 2.2.1 '@octokit/core': 5.1.0 '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.1.0) '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.1.0) - dev: false - /@actions/http-client@2.2.1: - resolution: {integrity: sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==} + '@actions/http-client@2.2.1': dependencies: tunnel: 0.0.6 undici: 5.28.3 - dev: false - /@aws-crypto/crc32@3.0.0: - resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + '@aws-crypto/crc32@3.0.0': dependencies: '@aws-crypto/util': 3.0.0 '@aws-sdk/types': 3.523.0 tslib: 1.14.1 - dev: false - /@aws-crypto/ie11-detection@3.0.0: - resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==} + '@aws-crypto/ie11-detection@3.0.0': dependencies: tslib: 1.14.1 - dev: false - /@aws-crypto/sha256-browser@3.0.0: - resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==} + '@aws-crypto/sha256-browser@3.0.0': dependencies: '@aws-crypto/ie11-detection': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 @@ -68,33 +458,24 @@ packages: '@aws-sdk/util-locate-window': 3.495.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 - dev: false - /@aws-crypto/sha256-js@3.0.0: - resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} + '@aws-crypto/sha256-js@3.0.0': dependencies: '@aws-crypto/util': 3.0.0 '@aws-sdk/types': 3.523.0 tslib: 1.14.1 - dev: false - /@aws-crypto/supports-web-crypto@3.0.0: - resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==} + '@aws-crypto/supports-web-crypto@3.0.0': dependencies: tslib: 1.14.1 - dev: false - /@aws-crypto/util@3.0.0: - resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + '@aws-crypto/util@3.0.0': dependencies: '@aws-sdk/types': 3.523.0 '@aws-sdk/util-utf8-browser': 3.259.0 tslib: 1.14.1 - dev: false - /@aws-sdk/client-route-53@3.529.1: - resolution: {integrity: sha512-osra30V5ILwEBeE1DUZreY7HYWQGco+WcQ1qg1UDSh/C0Nyxlu+8bVpwB/bjaldmy5Fi9MRv8SQsMdiAJFNp+w==} - engines: {node: '>=14.0.0'} + '@aws-sdk/client-route-53@3.529.1': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 @@ -141,13 +522,8 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false - /@aws-sdk/client-sso-oidc@3.529.1(@aws-sdk/credential-provider-node@3.529.1): - resolution: {integrity: sha512-bimxCWAvRnVcluWEQeadXvHyzWlBWsuGVligsaVZaGF0TLSn0eLpzpN9B1EhHzTf7m0Kh/wGtPSH1JxO6PpB+A==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@aws-sdk/credential-provider-node': ^3.529.1 + '@aws-sdk/client-sso-oidc@3.529.1(@aws-sdk/credential-provider-node@3.529.1)': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 @@ -191,11 +567,8 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false - /@aws-sdk/client-sso@3.529.1: - resolution: {integrity: sha512-KT1U/ZNjDhVv2ZgjzaeAn9VM7l667yeSguMrRYC8qk5h91/61MbjZypi6eOuKuVM+0fsQvzKScTQz0Lio0eYag==} - engines: {node: '>=14.0.0'} + '@aws-sdk/client-sso@3.529.1': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 @@ -237,13 +610,8 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false - /@aws-sdk/client-sts@3.529.1(@aws-sdk/credential-provider-node@3.529.1): - resolution: {integrity: sha512-Rvk2Sr3MACQTOtngUU+omlf4E17k47dRVXR7OFRD6Ow5iGgC9tkN2q/ExDPW/ktPOmM0lSgzWyQ6/PC/Zq3HUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@aws-sdk/credential-provider-node': ^3.529.1 + '@aws-sdk/client-sts@3.529.1(@aws-sdk/credential-provider-node@3.529.1)': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 @@ -286,11 +654,8 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false - /@aws-sdk/core@3.529.1: - resolution: {integrity: sha512-Sj42sYPfaL9PHvvciMICxhyrDZjqnnvFbPKDmQL5aFKyXy122qx7RdVqUOQERDmMQfvJh6+0W1zQlLnre89q4Q==} - engines: {node: '>=14.0.0'} + '@aws-sdk/core@3.529.1': dependencies: '@smithy/core': 1.3.8 '@smithy/protocol-http': 3.2.2 @@ -299,21 +664,15 @@ packages: '@smithy/types': 2.11.0 fast-xml-parser: 4.2.5 tslib: 2.6.2 - dev: false - /@aws-sdk/credential-provider-env@3.523.0: - resolution: {integrity: sha512-Y6DWdH6/OuMDoNKVzZlNeBc6f1Yjk1lYMjANKpIhMbkRCvLJw/PYZKOZa8WpXbTYdgg9XLjKybnLIb3ww3uuzA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-env@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/property-provider': 2.1.4 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/credential-provider-http@3.525.0: - resolution: {integrity: sha512-RNWQGuSBQZhl3iqklOslUEfQ4br1V3DCPboMpeqFtddUWJV3m2u2extFur9/4Uy+1EHVF120IwZUKtd8dF+ibw==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-http@3.525.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/fetch-http-handler': 2.4.5 @@ -324,11 +683,8 @@ packages: '@smithy/types': 2.11.0 '@smithy/util-stream': 2.1.5 tslib: 2.6.2 - dev: false - /@aws-sdk/credential-provider-ini@3.529.1(@aws-sdk/credential-provider-node@3.529.1): - resolution: {integrity: sha512-RjHsuTvHIwXG7a/3ERexemiD3c9riKMCZQzY2/b0Gg0ButEVbBcMfERtUzWmQ0V4ufe/PEZjP68MH1gupcoF9A==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-ini@3.529.1(@aws-sdk/credential-provider-node@3.529.1)': dependencies: '@aws-sdk/client-sts': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/credential-provider-env': 3.523.0 @@ -344,11 +700,8 @@ packages: transitivePeerDependencies: - '@aws-sdk/credential-provider-node' - aws-crt - dev: false - /@aws-sdk/credential-provider-node@3.529.1: - resolution: {integrity: sha512-mvY7F3dMmk/0dZOCfl5sUI1bG0osureBjxhELGCF0KkJqhWI0hIzh8UnPkYytSg3vdc97CMv7pTcozxrdA3b0g==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-node@3.529.1': dependencies: '@aws-sdk/credential-provider-env': 3.523.0 '@aws-sdk/credential-provider-http': 3.525.0 @@ -364,22 +717,16 @@ packages: tslib: 2.6.2 transitivePeerDependencies: - aws-crt - dev: false - /@aws-sdk/credential-provider-process@3.523.0: - resolution: {integrity: sha512-f0LP9KlFmMvPWdKeUKYlZ6FkQAECUeZMmISsv6NKtvPCI9e4O4cLTeR09telwDK8P0HrgcRuZfXM7E30m8re0Q==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-process@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/property-provider': 2.1.4 '@smithy/shared-ini-file-loader': 2.3.5 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/credential-provider-sso@3.529.1(@aws-sdk/credential-provider-node@3.529.1): - resolution: {integrity: sha512-KFMKkaoTGDgSJG+o9Ii7AglWG5JQeF6IFw9cXLMwDdIrp3KUmRcUIqe0cjOoCqeQEDGy0VHsimHmKKJ3894i/A==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-sso@3.529.1(@aws-sdk/credential-provider-node@3.529.1)': dependencies: '@aws-sdk/client-sso': 3.529.1 '@aws-sdk/token-providers': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) @@ -391,11 +738,8 @@ packages: transitivePeerDependencies: - '@aws-sdk/credential-provider-node' - aws-crt - dev: false - /@aws-sdk/credential-provider-web-identity@3.529.1(@aws-sdk/credential-provider-node@3.529.1): - resolution: {integrity: sha512-AGuZDOKN+AttjwTjrF47WLqzeEut2YynyxjkXZhxZF/xn8i5Y51kUAUdXsXw1bgR25pAeXQIdhsrQlRa1Pm5kw==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-web-identity@3.529.1(@aws-sdk/credential-provider-node@3.529.1)': dependencies: '@aws-sdk/client-sts': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 @@ -405,60 +749,42 @@ packages: transitivePeerDependencies: - '@aws-sdk/credential-provider-node' - aws-crt - dev: false - /@aws-sdk/middleware-host-header@3.523.0: - resolution: {integrity: sha512-4g3q7Ta9sdD9TMUuohBAkbx/e3I/juTqfKi7TPgP+8jxcYX72MOsgemAMHuP6CX27eyj4dpvjH+w4SIVDiDSmg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-host-header@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/protocol-http': 3.2.2 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/middleware-logger@3.523.0: - resolution: {integrity: sha512-PeDNJNhfiaZx54LBaLTXzUaJ9LXFwDFFIksipjqjvxMafnoVcQwKbkoPUWLe5ytT4nnL1LogD3s55mERFUsnwg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-logger@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/middleware-recursion-detection@3.523.0: - resolution: {integrity: sha512-nZ3Vt7ehfSDYnrcg/aAfjjvpdE+61B3Zk68i6/hSUIegT3IH9H1vSW67NDKVp+50hcEfzWwM2HMPXxlzuyFyrw==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-recursion-detection@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/protocol-http': 3.2.2 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/middleware-sdk-route53@3.523.0: - resolution: {integrity: sha512-d+SKqDBM3XCVkF/crRWwJD1WuS4PBY/CaTGwIyND1Z3o3ZCMhyo4f2ni19U+7ZtEULW50ZGznhB2F4GJHqpDUg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-sdk-route53@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/middleware-user-agent@3.525.0: - resolution: {integrity: sha512-4al/6uO+t/QIYXK2OgqzDKQzzLAYJza1vWFS+S0lJ3jLNGyLB5BMU5KqWjDzevYZ4eCnz2Nn7z0FveUTNz8YdQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-user-agent@3.525.0': dependencies: '@aws-sdk/types': 3.523.0 '@aws-sdk/util-endpoints': 3.525.0 '@smithy/protocol-http': 3.2.2 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/region-config-resolver@3.525.0: - resolution: {integrity: sha512-8kFqXk6UyKgTMi7N7QlhA6qM4pGPWbiUXqEY2RgUWngtxqNFGeM9JTexZeuavQI+qLLe09VPShPNX71fEDcM6w==} - engines: {node: '>=14.0.0'} + '@aws-sdk/region-config-resolver@3.525.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/node-config-provider': 2.2.5 @@ -466,11 +792,8 @@ packages: '@smithy/util-config-provider': 2.2.1 '@smithy/util-middleware': 2.1.4 tslib: 2.6.2 - dev: false - /@aws-sdk/token-providers@3.529.1(@aws-sdk/credential-provider-node@3.529.1): - resolution: {integrity: sha512-NpgMjsfpqiugbxrYGXtta914N43Mx/H0niidqv8wKMTgWQEtsJvYtOni+kuLXB+LmpjaMFNlpadooFU/bK4buA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/token-providers@3.529.1(@aws-sdk/credential-provider-node@3.529.1)': dependencies: '@aws-sdk/client-sso-oidc': 3.529.1(@aws-sdk/credential-provider-node@3.529.1) '@aws-sdk/types': 3.523.0 @@ -481,84 +804,51 @@ packages: transitivePeerDependencies: - '@aws-sdk/credential-provider-node' - aws-crt - dev: false - /@aws-sdk/types@3.523.0: - resolution: {integrity: sha512-AqGIu4u+SxPiUuNBp2acCVcq80KDUFjxe6e3cMTvKWTzCbrVk1AXv0dAaJnCmdkWIha6zJDWxpIk/aL4EGhZ9A==} - engines: {node: '>=14.0.0'} + '@aws-sdk/types@3.523.0': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/util-endpoints@3.525.0: - resolution: {integrity: sha512-DIW7WWU5tIGkeeKX6NJUyrEIdWMiqjLQG3XBzaUj+ufIENwNjdAHhlD8l2vX7Yr3JZRT6yN/84wBCj7Tw1xd1g==} - engines: {node: '>=14.0.0'} + '@aws-sdk/util-endpoints@3.525.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/types': 2.11.0 '@smithy/util-endpoints': 1.1.5 tslib: 2.6.2 - dev: false - /@aws-sdk/util-locate-window@3.495.0: - resolution: {integrity: sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/util-locate-window@3.495.0': dependencies: tslib: 2.6.2 - dev: false - /@aws-sdk/util-user-agent-browser@3.523.0: - resolution: {integrity: sha512-6ZRNdGHX6+HQFqTbIA5+i8RWzxFyxsZv8D3soRfpdyWIKkzhSz8IyRKXRciwKBJDaC7OX2jzGE90wxRQft27nA==} + '@aws-sdk/util-user-agent-browser@3.523.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/types': 2.11.0 bowser: 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/util-user-agent-node@3.525.0: - resolution: {integrity: sha512-88Wjt4efyUSBGcyIuh1dvoMqY1k15jpJc5A/3yi67clBQEFsu9QCodQCQPqmRjV3VRcMtBOk+jeCTiUzTY5dRQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - aws-crt: '>=1.0.0' - peerDependenciesMeta: - aws-crt: - optional: true + '@aws-sdk/util-user-agent-node@3.525.0': dependencies: '@aws-sdk/types': 3.523.0 '@smithy/node-config-provider': 2.2.5 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@aws-sdk/util-utf8-browser@3.259.0: - resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + '@aws-sdk/util-utf8-browser@3.259.0': dependencies: tslib: 2.6.2 - dev: false - /@aws-sdk/xml-builder@3.523.0: - resolution: {integrity: sha512-wfvyVymj2TUw7SuDor9IuFcAzJZvWRBZotvY/wQJOlYa3UP3Oezzecy64N4FWfBJEsZdrTN+HOZFl+IzTWWnUA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/xml-builder@3.523.0': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@fastify/busboy@2.1.1: - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - dev: false + '@fastify/busboy@2.1.1': {} - /@octokit/auth-token@4.0.0: - resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} - engines: {node: '>= 18'} - dev: false + '@octokit/auth-token@4.0.0': {} - /@octokit/core@5.1.0: - resolution: {integrity: sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==} - engines: {node: '>= 18'} + '@octokit/core@5.1.0': dependencies: '@octokit/auth-token': 4.0.0 '@octokit/graphql': 7.0.2 @@ -567,115 +857,72 @@ packages: '@octokit/types': 12.6.0 before-after-hook: 2.2.3 universal-user-agent: 6.0.1 - dev: false - /@octokit/endpoint@9.0.4: - resolution: {integrity: sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==} - engines: {node: '>= 18'} + '@octokit/endpoint@9.0.4': dependencies: '@octokit/types': 12.6.0 universal-user-agent: 6.0.1 - dev: false - /@octokit/graphql@7.0.2: - resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} - engines: {node: '>= 18'} + '@octokit/graphql@7.0.2': dependencies: '@octokit/request': 8.2.0 '@octokit/types': 12.6.0 universal-user-agent: 6.0.1 - dev: false - /@octokit/openapi-types@20.0.0: - resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} - dev: false + '@octokit/openapi-types@20.0.0': {} - /@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.1.0): - resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '5' + '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.1.0)': dependencies: '@octokit/core': 5.1.0 '@octokit/types': 12.6.0 - dev: false - /@octokit/plugin-request-log@4.0.1(@octokit/core@5.1.0): - resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '5' + '@octokit/plugin-request-log@4.0.1(@octokit/core@5.1.0)': dependencies: '@octokit/core': 5.1.0 - dev: false - /@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.1.0): - resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} - engines: {node: '>= 18'} - peerDependencies: - '@octokit/core': '5' + '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.1.0)': dependencies: '@octokit/core': 5.1.0 '@octokit/types': 12.6.0 - dev: false - /@octokit/request-error@5.0.1: - resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} - engines: {node: '>= 18'} + '@octokit/request-error@5.0.1': dependencies: '@octokit/types': 12.6.0 deprecation: 2.3.1 once: 1.4.0 - dev: false - /@octokit/request@8.2.0: - resolution: {integrity: sha512-exPif6x5uwLqv1N1irkLG1zZNJkOtj8bZxuVHd71U5Ftuxf2wGNvAJyNBcPbPC+EBzwYEbBDdSFb8EPcjpYxPQ==} - engines: {node: '>= 18'} + '@octokit/request@8.2.0': dependencies: '@octokit/endpoint': 9.0.4 '@octokit/request-error': 5.0.1 '@octokit/types': 12.6.0 universal-user-agent: 6.0.1 - dev: false - /@octokit/rest@20.0.2: - resolution: {integrity: sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==} - engines: {node: '>= 18'} + '@octokit/rest@20.0.2': dependencies: '@octokit/core': 5.1.0 '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.1.0) '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.1.0) '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.1.0) - dev: false - /@octokit/types@12.6.0: - resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} + '@octokit/types@12.6.0': dependencies: '@octokit/openapi-types': 20.0.0 - dev: false - /@smithy/abort-controller@2.1.4: - resolution: {integrity: sha512-66HO817oIZ2otLIqy06R5muapqZjkgF1jfU0wyNko8cuqZNu8nbS9ljlhcRYw/M/uWRJzB9ih81DLSHhYbBLlQ==} - engines: {node: '>=14.0.0'} + '@smithy/abort-controller@2.1.4': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/config-resolver@2.1.5: - resolution: {integrity: sha512-LcBB5JQC3Tx2ZExIJzfvWaajhFIwHrUNQeqxhred2r5nnqrdly9uoCrvM1sxOOdghYuWWm2Kr8tBCDOmxsgeTA==} - engines: {node: '>=14.0.0'} + '@smithy/config-resolver@2.1.5': dependencies: '@smithy/node-config-provider': 2.2.5 '@smithy/types': 2.11.0 '@smithy/util-config-provider': 2.2.1 '@smithy/util-middleware': 2.1.4 tslib: 2.6.2 - dev: false - /@smithy/core@1.3.8: - resolution: {integrity: sha512-6cFhQ9ChU7MxvOXJn6nuUSONacpNsGHWhfueROQuM/0vibDdZA9FWEdNbVkuVuc+BFI5BnaX3ltERUlpUirpIA==} - engines: {node: '>=14.0.0'} + '@smithy/core@1.3.8': dependencies: '@smithy/middleware-endpoint': 2.4.6 '@smithy/middleware-retry': 2.1.7 @@ -685,74 +932,53 @@ packages: '@smithy/types': 2.11.0 '@smithy/util-middleware': 2.1.4 tslib: 2.6.2 - dev: false - /@smithy/credential-provider-imds@2.2.6: - resolution: {integrity: sha512-+xQe4Pite0kdk9qn0Vyw5BRVh0iSlj+T4TEKRXr4E1wZKtVgIzGlkCrfICSjiPVFkPxk4jMpVboMYdEiiA88/w==} - engines: {node: '>=14.0.0'} + '@smithy/credential-provider-imds@2.2.6': dependencies: '@smithy/node-config-provider': 2.2.5 '@smithy/property-provider': 2.1.4 '@smithy/types': 2.11.0 '@smithy/url-parser': 2.1.4 tslib: 2.6.2 - dev: false - /@smithy/eventstream-codec@2.1.4: - resolution: {integrity: sha512-UkiieTztP7adg8EuqZvB0Y4LewdleZCJU7Kgt9RDutMsRYqO32fMpWeQHeTHaIMosmzcRZUykMRrhwGJe9mP3A==} + '@smithy/eventstream-codec@2.1.4': dependencies: '@aws-crypto/crc32': 3.0.0 '@smithy/types': 2.11.0 '@smithy/util-hex-encoding': 2.1.1 tslib: 2.6.2 - dev: false - /@smithy/fetch-http-handler@2.4.5: - resolution: {integrity: sha512-FR1IMGdo0yRFs1tk71zRGSa1MznVLQOVNaPjyNtx6dOcy/u0ovEnXN5NVz6slw5KujFlg3N1w4+UbO8F3WyYUg==} + '@smithy/fetch-http-handler@2.4.5': dependencies: '@smithy/protocol-http': 3.2.2 '@smithy/querystring-builder': 2.1.4 '@smithy/types': 2.11.0 '@smithy/util-base64': 2.2.1 tslib: 2.6.2 - dev: false - /@smithy/hash-node@2.1.4: - resolution: {integrity: sha512-uvCcpDLXaTTL0X/9ezF8T8sS77UglTfZVQaUOBiCvR0QydeSyio3t0Hj3QooVdyFsKTubR8gCk/ubLk3vAyDng==} - engines: {node: '>=14.0.0'} + '@smithy/hash-node@2.1.4': dependencies: '@smithy/types': 2.11.0 '@smithy/util-buffer-from': 2.1.1 '@smithy/util-utf8': 2.2.0 tslib: 2.6.2 - dev: false - /@smithy/invalid-dependency@2.1.4: - resolution: {integrity: sha512-QzlNBl6jt3nb9jNnE51wTegReVvUdozyMMrFEyb/rc6AzPID1O+qMJYjAAoNw098y0CZVfCpEnoK2+mfBOd8XA==} + '@smithy/invalid-dependency@2.1.4': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/is-array-buffer@2.1.1: - resolution: {integrity: sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==} - engines: {node: '>=14.0.0'} + '@smithy/is-array-buffer@2.1.1': dependencies: tslib: 2.6.2 - dev: false - /@smithy/middleware-content-length@2.1.4: - resolution: {integrity: sha512-C6VRwfcr0w9qRFhDGCpWMVhlEIBFlmlPRP1aX9Cv9xDj9SUwlDrNvoV1oP1vjRYuLxCDgovBBynCwwcluS2wLw==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-content-length@2.1.4': dependencies: '@smithy/protocol-http': 3.2.2 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/middleware-endpoint@2.4.6: - resolution: {integrity: sha512-AsXtUXHPOAS0EGZUSFOsVJvc7p0KL29PGkLxLfycPOcFVLru/oinYB6yvyL73ZZPX2OB8sMYUMrj7eH2kI7V/w==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-endpoint@2.4.6': dependencies: '@smithy/middleware-serde': 2.2.1 '@smithy/node-config-provider': 2.2.5 @@ -761,11 +987,8 @@ packages: '@smithy/url-parser': 2.1.4 '@smithy/util-middleware': 2.1.4 tslib: 2.6.2 - dev: false - /@smithy/middleware-retry@2.1.7: - resolution: {integrity: sha512-8fOP/cJN4oMv+5SRffZC8RkqfWxHqGgn/86JPINY/1DnTRegzf+G5GT9lmIdG1YasuSbU7LISfW9PXil3isPVw==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-retry@2.1.7': dependencies: '@smithy/node-config-provider': 2.2.5 '@smithy/protocol-http': 3.2.2 @@ -776,96 +999,63 @@ packages: '@smithy/util-retry': 2.1.4 tslib: 2.6.2 uuid: 8.3.2 - dev: false - /@smithy/middleware-serde@2.2.1: - resolution: {integrity: sha512-VAWRWqnNjgccebndpyK94om4ZTYzXLQxUmNCXYzM/3O9MTfQjTNBgtFtQwyIIez6z7LWcCsXmnKVIOE9mLqAHQ==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-serde@2.2.1': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/middleware-stack@2.1.4: - resolution: {integrity: sha512-Qqs2ba8Ax1rGKOSGJS2JN23fhhox2WMdRuzx0NYHtXzhxbJOIMmz9uQY6Hf4PY8FPteBPp1+h0j5Fmr+oW12sg==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-stack@2.1.4': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/node-config-provider@2.2.5: - resolution: {integrity: sha512-CxPf2CXhjO79IypHJLBATB66Dw6suvr1Yc2ccY39hpR6wdse3pZ3E8RF83SODiNH0Wjmkd0ze4OF8exugEixgA==} - engines: {node: '>=14.0.0'} + '@smithy/node-config-provider@2.2.5': dependencies: '@smithy/property-provider': 2.1.4 '@smithy/shared-ini-file-loader': 2.3.5 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/node-http-handler@2.4.3: - resolution: {integrity: sha512-bD5zRdEl1u/4vAAMeQnGEUNbH1seISV2Z0Wnn7ltPRl/6B2zND1R9XzTfsOnH1R5jqghpochF/mma8u7uXz0qQ==} - engines: {node: '>=14.0.0'} + '@smithy/node-http-handler@2.4.3': dependencies: '@smithy/abort-controller': 2.1.4 '@smithy/protocol-http': 3.2.2 '@smithy/querystring-builder': 2.1.4 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/property-provider@2.1.4: - resolution: {integrity: sha512-nWaY/MImj1BiXZ9WY65h45dcxOx8pl06KYoHxwojDxDL+Q9yLU1YnZpgv8zsHhEftlj9KhePENjQTlNowWVyug==} - engines: {node: '>=14.0.0'} + '@smithy/property-provider@2.1.4': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/protocol-http@3.2.2: - resolution: {integrity: sha512-xYBlllOQcOuLoxzhF2u8kRHhIFGQpDeTQj/dBSnw4kfI29WMKL5RnW1m9YjnJAJ49miuIvrkJR+gW5bCQ+Mchw==} - engines: {node: '>=14.0.0'} + '@smithy/protocol-http@3.2.2': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/querystring-builder@2.1.4: - resolution: {integrity: sha512-LXSL0J/nRWvGT+jIj+Fip3j0J1ZmHkUyBFRzg/4SmPNCLeDrtVu7ptKOnTboPsFZu5BxmpYok3kJuQzzRdrhbw==} - engines: {node: '>=14.0.0'} + '@smithy/querystring-builder@2.1.4': dependencies: '@smithy/types': 2.11.0 '@smithy/util-uri-escape': 2.1.1 tslib: 2.6.2 - dev: false - /@smithy/querystring-parser@2.1.4: - resolution: {integrity: sha512-U2b8olKXgZAs0eRo7Op11jTNmmcC/sqYmsA7vN6A+jkGnDvJlEl7AetUegbBzU8q3D6WzC5rhR/joIy8tXPzIg==} - engines: {node: '>=14.0.0'} + '@smithy/querystring-parser@2.1.4': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/service-error-classification@2.1.4: - resolution: {integrity: sha512-JW2Hthy21evnvDmYYk1kItOmbp3X5XI5iqorXgFEunb6hQfSDZ7O1g0Clyxg7k/Pcr9pfLk5xDIR2To/IohlsQ==} - engines: {node: '>=14.0.0'} + '@smithy/service-error-classification@2.1.4': dependencies: '@smithy/types': 2.11.0 - dev: false - /@smithy/shared-ini-file-loader@2.3.5: - resolution: {integrity: sha512-oI99+hOvsM8oAJtxAGmoL/YCcGXtbP0fjPseYGaNmJ4X5xOFTer0KPk7AIH3AL6c5AlYErivEi1X/X78HgTVIw==} - engines: {node: '>=14.0.0'} + '@smithy/shared-ini-file-loader@2.3.5': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/signature-v4@2.1.4: - resolution: {integrity: sha512-gnu9gCn0qQ8IdhNjs6o3QVCXzUs33znSDYwVMWo3nX4dM6j7z9u6FC302ShYyVWfO4MkVMuGCCJ6nl3PcH7V1Q==} - engines: {node: '>=14.0.0'} + '@smithy/signature-v4@2.1.4': dependencies: '@smithy/eventstream-codec': 2.1.4 '@smithy/is-array-buffer': 2.1.1 @@ -875,11 +1065,8 @@ packages: '@smithy/util-uri-escape': 2.1.1 '@smithy/util-utf8': 2.2.0 tslib: 2.6.2 - dev: false - /@smithy/smithy-client@2.4.5: - resolution: {integrity: sha512-igXOM4kPXPo6b5LZXTUqTnrGk20uVd8OXoybC3f89gczzGfziLK4yUNOmiHSdxY9OOMOnnhVe5MpTm01MpFqvA==} - engines: {node: '>=14.0.0'} + '@smithy/smithy-client@2.4.5': dependencies: '@smithy/middleware-endpoint': 2.4.6 '@smithy/middleware-stack': 2.1.4 @@ -887,74 +1074,49 @@ packages: '@smithy/types': 2.11.0 '@smithy/util-stream': 2.1.5 tslib: 2.6.2 - dev: false - /@smithy/types@2.11.0: - resolution: {integrity: sha512-AR0SXO7FuAskfNhyGfSTThpLRntDI5bOrU0xrpVYU0rZyjl3LBXInZFMTP/NNSd7IS6Ksdtar0QvnrPRIhVrLQ==} - engines: {node: '>=14.0.0'} + '@smithy/types@2.11.0': dependencies: tslib: 2.6.2 - dev: false - /@smithy/url-parser@2.1.4: - resolution: {integrity: sha512-1hTy6UYRYqOZlHKH2/2NzdNQ4NNmW2Lp0sYYvztKy+dEQuLvZL9w88zCzFQqqFer3DMcscYOshImxkJTGdV+rg==} + '@smithy/url-parser@2.1.4': dependencies: '@smithy/querystring-parser': 2.1.4 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/util-base64@2.2.1: - resolution: {integrity: sha512-troGfokrpoqv8TGgsb8p4vvM71vqor314514jyQ0i9Zae3qs0jUVbSMCIBB1tseVynXFRcZJAZ9hPQYlifLD5A==} - engines: {node: '>=14.0.0'} + '@smithy/util-base64@2.2.1': dependencies: '@smithy/util-buffer-from': 2.1.1 '@smithy/util-utf8': 2.2.0 tslib: 2.6.2 - dev: false - /@smithy/util-body-length-browser@2.1.1: - resolution: {integrity: sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==} + '@smithy/util-body-length-browser@2.1.1': dependencies: tslib: 2.6.2 - dev: false - /@smithy/util-body-length-node@2.2.2: - resolution: {integrity: sha512-U7DooaT1SfW7XHrOcxthYJnQ+WMaefRrFPxW5Qmypw38Ivv+TKvfVuVHA9V162h8BeW9rzOJwOunjgXd0DdB4w==} - engines: {node: '>=14.0.0'} + '@smithy/util-body-length-node@2.2.2': dependencies: tslib: 2.6.2 - dev: false - /@smithy/util-buffer-from@2.1.1: - resolution: {integrity: sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==} - engines: {node: '>=14.0.0'} + '@smithy/util-buffer-from@2.1.1': dependencies: '@smithy/is-array-buffer': 2.1.1 tslib: 2.6.2 - dev: false - /@smithy/util-config-provider@2.2.1: - resolution: {integrity: sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==} - engines: {node: '>=14.0.0'} + '@smithy/util-config-provider@2.2.1': dependencies: tslib: 2.6.2 - dev: false - /@smithy/util-defaults-mode-browser@2.1.7: - resolution: {integrity: sha512-vvIpWsysEdY77R0Qzr6+LRW50ye7eii7AyHM0OJnTi0isHYiXo5M/7o4k8gjK/b1upQJdfjzSBoJVa2SWrI+2g==} - engines: {node: '>= 10.0.0'} + '@smithy/util-defaults-mode-browser@2.1.7': dependencies: '@smithy/property-provider': 2.1.4 '@smithy/smithy-client': 2.4.5 '@smithy/types': 2.11.0 bowser: 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/util-defaults-mode-node@2.2.7: - resolution: {integrity: sha512-qzXkSDyU6Th+rNNcNkG4a7Ix7m5HlMOtSCPxTVKlkz7eVsqbSSPggegbFeQJ2MVELBB4wnzNPsVPJIrpIaJpXA==} - engines: {node: '>= 10.0.0'} + '@smithy/util-defaults-mode-node@2.2.7': dependencies: '@smithy/config-resolver': 2.1.5 '@smithy/credential-provider-imds': 2.2.6 @@ -963,44 +1125,29 @@ packages: '@smithy/smithy-client': 2.4.5 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/util-endpoints@1.1.5: - resolution: {integrity: sha512-tgDpaUNsUtRvNiBulKU1VnpoXU1GINMfZZXunRhUXOTBEAufG1Wp79uDXLau2gg1RZ4dpAR6lXCkrmddihCGUg==} - engines: {node: '>= 14.0.0'} + '@smithy/util-endpoints@1.1.5': dependencies: '@smithy/node-config-provider': 2.2.5 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/util-hex-encoding@2.1.1: - resolution: {integrity: sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==} - engines: {node: '>=14.0.0'} + '@smithy/util-hex-encoding@2.1.1': dependencies: tslib: 2.6.2 - dev: false - /@smithy/util-middleware@2.1.4: - resolution: {integrity: sha512-5yYNOgCN0DL0OplME0pthoUR/sCfipnROkbTO7m872o0GHCVNJj5xOFJ143rvHNA54+pIPMLum4z2DhPC2pVGA==} - engines: {node: '>=14.0.0'} + '@smithy/util-middleware@2.1.4': dependencies: '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/util-retry@2.1.4: - resolution: {integrity: sha512-JRZwhA3fhkdenSEYIWatC8oLwt4Bdf2LhHbNQApqb7yFoIGMl4twcYI3BcJZ7YIBZrACA9jGveW6tuCd836XzQ==} - engines: {node: '>= 14.0.0'} + '@smithy/util-retry@2.1.4': dependencies: '@smithy/service-error-classification': 2.1.4 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /@smithy/util-stream@2.1.5: - resolution: {integrity: sha512-FqvBFeTgx+QC4+i8USHqU8Ifs9nYRpW/OBfksojtgkxPIQ2H7ypXDEbnQRAV7PwoNHWcSwPomLYi0svmQQG5ow==} - engines: {node: '>=14.0.0'} + '@smithy/util-stream@2.1.5': dependencies: '@smithy/fetch-http-handler': 2.4.5 '@smithy/node-http-handler': 2.4.3 @@ -1010,90 +1157,50 @@ packages: '@smithy/util-hex-encoding': 2.1.1 '@smithy/util-utf8': 2.2.0 tslib: 2.6.2 - dev: false - /@smithy/util-uri-escape@2.1.1: - resolution: {integrity: sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==} - engines: {node: '>=14.0.0'} + '@smithy/util-uri-escape@2.1.1': dependencies: tslib: 2.6.2 - dev: false - /@smithy/util-utf8@2.2.0: - resolution: {integrity: sha512-hBsKr5BqrDrKS8qy+YcV7/htmMGxriA1PREOf/8AGBhHIZnfilVv1Waf1OyKhSbFW15U/8+gcMUQ9/Kk5qwpHQ==} - engines: {node: '>=14.0.0'} + '@smithy/util-utf8@2.2.0': dependencies: '@smithy/util-buffer-from': 2.1.1 tslib: 2.6.2 - dev: false - /@smithy/util-waiter@2.1.4: - resolution: {integrity: sha512-AK17WaC0hx1wR9juAOsQkJ6DjDxBGEf5TrKhpXtNFEn+cVto9Li3MVsdpAO97AF7bhFXSyC8tJA3F4ThhqwCdg==} - engines: {node: '>=14.0.0'} + '@smithy/util-waiter@2.1.4': dependencies: '@smithy/abort-controller': 2.1.4 '@smithy/types': 2.11.0 tslib: 2.6.2 - dev: false - /before-after-hook@2.2.3: - resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - dev: false + before-after-hook@2.2.3: {} - /bowser@2.11.0: - resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} - dev: false + bowser@2.11.0: {} - /deprecation@2.3.1: - resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} - dev: false + deprecation@2.3.1: {} - /fast-xml-parser@4.2.5: - resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} - hasBin: true + fast-xml-parser@4.2.5: dependencies: strnum: 1.0.5 - dev: false - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + once@1.4.0: dependencies: wrappy: 1.0.2 - dev: false - /strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} - dev: false + strnum@1.0.5: {} - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: false + tslib@1.14.1: {} - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: false + tslib@2.6.2: {} - /tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - dev: false + tunnel@0.0.6: {} - /undici@5.28.3: - resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==} - engines: {node: '>=14.0'} + undici@5.28.3: dependencies: '@fastify/busboy': 2.1.1 - dev: false - /universal-user-agent@6.0.1: - resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} - dev: false + universal-user-agent@6.0.1: {} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false + uuid@8.3.2: {} - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false + wrappy@1.0.2: {} diff --git a/.github/scripts/jira/package.json b/.github/scripts/jira/package.json index 69f307c550..2c57d35a64 100644 --- a/.github/scripts/jira/package.json +++ b/.github/scripts/jira/package.json @@ -8,6 +8,10 @@ "keywords": [], "author": "", "license": "MIT", + "engines": { + "node": ">=18", + "pnpm": ">=9" + }, "dependencies": { "@actions/core": "^1.10.1", "node-fetch": "^2.7.0" diff --git a/.github/scripts/jira/pnpm-lock.yaml b/.github/scripts/jira/pnpm-lock.yaml index e6e4d82b15..09ba8c749c 100644 --- a/.github/scripts/jira/pnpm-lock.yaml +++ b/.github/scripts/jira/pnpm-lock.yaml @@ -1,39 +1,33 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@actions/core': - specifier: ^1.10.1 - version: 1.10.1 - node-fetch: - specifier: ^2.7.0 - version: 2.7.0 +importers: + + .: + dependencies: + '@actions/core': + specifier: ^1.10.1 + version: 1.10.1 + node-fetch: + specifier: ^2.7.0 + version: 2.7.0 packages: - /@actions/core@1.10.1: + '@actions/core@1.10.1': resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} - dependencies: - '@actions/http-client': 2.2.1 - uuid: 8.3.2 - dev: false - /@actions/http-client@2.2.1: + '@actions/http-client@2.2.1': resolution: {integrity: sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==} - dependencies: - tunnel: 0.0.6 - undici: 5.28.4 - dev: false - /@fastify/busboy@2.1.1: + '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - dev: false - /node-fetch@2.7.0: + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} peerDependencies: @@ -41,38 +35,59 @@ packages: peerDependenciesMeta: encoding: optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - /tr46@0.0.3: + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - /tunnel@0.0.6: + tunnel@0.0.6: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - dev: false - /undici@5.28.4: + undici@5.28.4: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} - dependencies: - '@fastify/busboy': 2.1.1 - dev: false - /uuid@8.3.2: + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - dev: false - /webidl-conversions@3.0.1: + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false - /whatwg-url@5.0.0: + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + +snapshots: + + '@actions/core@1.10.1': + dependencies: + '@actions/http-client': 2.2.1 + uuid: 8.3.2 + + '@actions/http-client@2.2.1': + dependencies: + tunnel: 0.0.6 + undici: 5.28.4 + + '@fastify/busboy@2.1.1': {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + tr46@0.0.3: {} + + tunnel@0.0.6: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + + uuid@8.3.2: {} + + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: false diff --git a/.github/scripts/jira/update-jira-issue.js b/.github/scripts/jira/update-jira-issue.js index 5977381052..77d5b81bff 100644 --- a/.github/scripts/jira/update-jira-issue.js +++ b/.github/scripts/jira/update-jira-issue.js @@ -94,6 +94,10 @@ async function run() { core.notice( "No JIRA issue number found in: PR title, commit message, or branch name. Please include the issue ID in one of these." ); + core.setOutput( + "jiraComment", + "> :medal_military: No JIRA issue number found - Please include it in the PR title or in a commit message." + ); return; } const fixVersionName = `chainlink-v${chainlinkVersion}`; @@ -105,6 +109,7 @@ async function run() { tags, fixVersionName ); + core.setOutput("jiraComment", ""); } catch (error) { core.setFailed(error.message); } diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index 0b0404e0e0..c1a8d9edc9 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -66,7 +66,7 @@ jobs: QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} suites: benchmark chaos reorg load - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 env: DETACH_RUNNER: true TEST_SUITE: benchmark diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index d3f0254446..d56ee2e74c 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -82,7 +82,7 @@ jobs: QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} suites: benchmark chaos reorg load - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 env: RR_CPU: 4000m RR_MEM: 4Gi diff --git a/.github/workflows/automation-nightly-tests.yml b/.github/workflows/automation-nightly-tests.yml index c4c6a4be06..a71e874c97 100644 --- a/.github/workflows/automation-nightly-tests.yml +++ b/.github/workflows/automation-nightly-tests.yml @@ -88,7 +88,7 @@ jobs: with: ref: ${{ github.head_ref || github.ref_name }} - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -114,7 +114,7 @@ jobs: grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 env: TEST_SUITE: ${{ matrix.tests.suite }} with: diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index a42ddf81e5..741603eddb 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -155,7 +155,7 @@ jobs: os: ubuntu-latest enabled: ${{ inputs.enableReorg }} pyroscope_env: ci-automation-on-demand-reorg - network: SIMULATED_NONDEV + network: SIMULATED command: -run ^TestAutomationReorg$ ./reorg - name: upgrade 2.0 id: upgrade-2.0 @@ -218,7 +218,7 @@ jobs: echo "version=${{ inputs.chainlinkVersionUpdate }}" >>$GITHUB_OUTPUT fi - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -313,7 +313,7 @@ jobs: echo ::add-mask::$BASE64_CONFIG_OVERRIDE echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 if: ${{ matrix.tests.enabled == true }} env: TEST_SUITE: ${{ matrix.tests.suite }} diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index e88ad92e29..e5853d374c 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -68,7 +68,7 @@ jobs: uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 if: ${{ steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true' }} with: - version: ^8.0.0 + version: ^9.0.0 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 @@ -88,6 +88,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update Jira ticket for core + id: jira if: ${{ steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true' }} shell: bash working-directory: ./.github/scripts/jira @@ -108,10 +109,12 @@ jobs: if: ${{ steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_COMMENT: ${{ steps.jira.outputs.jiraComment }} with: message: | I see you updated files related to `core`. Please run `pnpm changeset` in the root directory to add a changeset as well as in the text include at least one of the following tags: ${{ env.TAGS }} + ${{ env.JIRA_COMMENT }} reactions: eyes comment_tag: changeset-core mode: ${{ steps.files-changed.outputs.core-changeset == 'false' && 'upsert' || 'delete' }} @@ -149,10 +152,12 @@ jobs: if: ${{ steps.files-changed.outputs.core-changeset == 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_COMMENT: ${{ steps.jira.outputs.jiraComment }} with: message: | I see you added a changeset file but it does not contain a tag. Please edit the text include at least one of the following tags: ${{ env.TAGS }} + ${{ env.JIRA_COMMENT }} reactions: eyes comment_tag: changeset-core-tags mode: ${{ steps.changeset-tags.outputs.has_tags == 'false' && 'upsert' || 'delete' }} diff --git a/.github/workflows/changesets-preview-pr.yml b/.github/workflows/changesets-preview-pr.yml index 03d1fecf61..94dc1635c4 100644 --- a/.github/workflows/changesets-preview-pr.yml +++ b/.github/workflows/changesets-preview-pr.yml @@ -31,7 +31,7 @@ jobs: uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 if: steps.change.outputs.core-changeset == 'true' with: - version: ^8.0.0 + version: ^9.0.0 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 456ed07928..3a552babf0 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -71,7 +71,7 @@ jobs: gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - name: Notify Slack - if: ${{ failure() && (github.event_name == 'merge_group' || github.event.branch == 'develop') && needs.filter.outputs.changes == 'true' }} + if: ${{ failure() && github.event.schedule != '' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 env: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index 296a1a3cf0..b46336dd2a 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -1,26 +1,240 @@ name: Client Compatibility Tests on: schedule: - - cron: "30 5 * * *" # Run every night at midnight + 30min EST + - cron: "30 5 * * TUE,FRI" # Run every Tuesday and Friday at midnight + 30min EST push: tags: - "*" + merge_group: + pull_request: workflow_dispatch: + inputs: + chainlinkVersion: + description: commit SHA or tag of the Chainlink version to test + required: false + type: string + evmImplementations: + description: comma separated list of EVM implementations to test (ignored if base64TestList is used) + required: true + type: string + default: "geth,besu,nethermind,erigon" + latestVersionsNumber: + description: how many of latest images of EVM implementations to test with (ignored if base64TestList is used) + required: true + type: number + default: 3 + base64TestList: + description: base64 encoded list of tests to run (same as base64-ed output of testlistgenerator tool) + required: false + type: string env: CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com MOD_CACHE_VERSION: 2 +concurrency: + group: ${{ github.ref }}-${{ github.repository }}-${{ github.event_name }}--evm-compatibility-tests + cancel-in-progress: true + jobs: # Build Test Dependencies + check-dependency-bump: + name: Check for go-ethereum dependency bump + if: github.event_name == 'pull_request' || github.event_name == 'merge_queue' + runs-on: ubuntu-latest + outputs: + dependency_changed: ${{ steps.changes.outputs.dependency_changed }} + steps: + - name: Checkout code + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + fetch-depth: 0 + - name: Check for go.mod changes + id: changes + run: | + git fetch origin ${{ github.base_ref }} + # if no match is found then grep exits with code 1, but if there is a match it exits with code 0 + # this will return a match if there are any changes on that corresponding line, for example if spacing was changed + DEPENDENCY_CHANGED=$(git diff -U0 origin/${{ github.base_ref }}...HEAD -- go.mod | grep -q 'github.com/ethereum/go-ethereum'; echo $?) + PR_VERSION=$(grep 'github.com/ethereum/go-ethereum' go.mod | awk '{print $2}') + + # here 0 means a match was found, 1 means no match was found + if [ "$DEPENDENCY_CHANGED" -eq 0 ]; then + # Dependency was changed in the PR, now compare with the base branch + git fetch origin ${{ github.base_ref }} + BASE_VERSION=$(git show origin/${{ github.base_ref }}:go.mod | grep 'github.com/ethereum/go-ethereum' | awk '{print $2}') + + echo "Base branch version: $BASE_VERSION" + echo "PR branch version: $PR_VERSION" + + echo "Dependency version changed in the PR compared to the base branch." + echo "dependency_changed=true" >> $GITHUB_OUTPUT + else + echo "No changes to ethereum/go-ethereum dependency in the PR." + echo "PR branch version: $PR_VERSION" + echo "dependency_changed=false" >> $GITHUB_OUTPUT + fi + + should-run: + if: always() + name: Check if the job should run + needs: check-dependency-bump + runs-on: ubuntu-latest + outputs: + should_run: ${{ steps.should-run.outputs.should_run }} + eth_implementations : ${{ steps.should-run.outputs.eth_implementations }} + env: + GITHUB_REF_TYPE: ${{ github.ref_type }} + steps: + - name: Check if the job should run + id: should-run + run: | + if [ "${{ needs.check-dependency-bump.outputs.dependency_changed }}" == "true" ]; then + echo "Will run tests, because go-ethereum dependency was bumped" + echo "should_run=true" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" = "schedule" ]; then + echo "Will run tests, because trigger event was $GITHUB_EVENT_NAME" + echo "should_run=true" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then + echo "Will run tests, because trigger event was $GITHUB_EVENT_NAME" + echo "should_run=true" >> $GITHUB_OUTPUT + elif [ "$GITHUB_REF_TYPE" = "tag" ]; then + echo "Will run tests, because new tag was created" + echo "should_run=true" >> $GITHUB_OUTPUT + else + echo "Will not run tests" + echo "should_run=false" >> $GITHUB_OUTPUT + fi + + select-versions: + if: always() && needs.should-run.outputs.should_run == 'true' + name: Select Versions + needs: should-run + runs-on: ubuntu-latest + env: + RELEASED_DAYS_AGO: 4 + GITHUB_REF_TYPE: ${{ github.ref_type }} + outputs: + evm_implementations : ${{ steps.select-implementations.outputs.evm_implementations }} + chainlink_version: ${{ steps.select-chainlink-version.outputs.chainlink_version }} + latest_image_count: ${{ steps.get-image-count.outputs.image_count }} + steps: + # ghlatestreleasechecker is a tool to check if new release is available for a given repo + - name: Set Up ghlatestreleasechecker + shell: bash + run: | + go install github.com/smartcontractkit/chainlink-testing-framework/tools/ghlatestreleasechecker@v1.0.0 + - name: Select EVM implementations to test + id: select-implementations + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then + echo "Checking for new releases" + implementations_arr=() + new_geth=$(ghlatestreleasechecker "ethereum/go-ethereum" $RELEASED_DAYS_AGO) + if [ "$new_geth" != "none" ]; then + echo "New geth release found: $new_geth" + implementations_arr+=("geth") + fi + new_besu=$(ghlatestreleasechecker "hyperledger/besu" $RELEASED_DAYS_AGO) + if [ "$new_besu" != "none" ]; then + echo "New besu release found: $new_besu" + implementations_arr+=("besu") + fi + new_erigon=$(ghlatestreleasechecker "ledgerwatch/erigon" $RELEASED_DAYS_AGO) + if [ "$new_erigon" != "none" ]; then + echo "New erigon release found: $new_erigon" + implementations_arr+=("erigon") + fi + new_nethermind=$(ghlatestreleasechecker "nethermindEth/nethermind" $RELEASED_DAYS_AGO) + if [ "$new_nethermind" != "none" ]; then + echo "New nethermind release found: $new_nethermind" + implementations_arr+=("nethermind") + fi + IFS=',' + eth_implementations="${implementations_arr[*]}" + echo "Found new releases for: $eth_implementations" + echo "evm_implementations=$eth_implementations" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then + if [ -n "${{ github.event.inputs.base64TestList }}" ]; then + echo "Base64-ed Test Input provided, ignoring EVM implementations" + else + echo "Will test following EVM implementations: ${{ github.event.inputs.evmImplementations }}" + echo "evm_implementations=${{ github.event.inputs.evmImplementations }}" >> $GITHUB_OUTPUT + fi + else + echo "Will test all EVM implementations" + echo "evm_implementations=geth,besu,nethermind,erigon" >> $GITHUB_OUTPUT + fi + - name: Select Chainlink version + id: select-chainlink-version + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + if [ "$GITHUB_EVENT_NAME" = "schedule" ]; then + echo "Fetching latest Chainlink stable version" + implementations_arr=() + # we use 100 days since we really want the latest one, and it's highly improbable there won't be a release in last 100 days + chainlink_version=$(ghlatestreleasechecker "smartcontractkit/chainlink" 100) + echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then + echo "Fetching Chainlink version from input" + if [ -n "${{ github.event.inputs.chainlinkVersion }}" ]; then + echo "Chainlink version provided in input" + chainlink_version="${{ github.event.inputs.chainlinkVersion }}" + else + echo "Chainlink version not provided in input. Using latest commit SHA." + chainlink_version=${{ github.sha }} + fi + echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then + echo "Fetching Chainlink version from PR's head commit" + chainlink_version="${{ github.event.pull_request.head.sha }}" + echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + elif [ "$GITHUB_EVENT_NAME" = "merge_queue" ]; then + echo "Fetching Chainlink version from merge queue's head commit" + chainlink_version="${{ github.event.merge_group.head_sha }}" + echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + elif [ "$GITHUB_REF_TYPE" = "tag" ]; then + echo "Fetching Chainlink version from tag" + chainlink_version="${{ github.ref }}" + echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + else + echo "Unsupported trigger event. It's probably an issue with the pipeline definition. Please reach out to the Test Tooling team." + exit 1 + fi + echo "Will use following Chainlink version: $chainlink_version" + - name: Get image count + id: get-image-count + run: | + if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then + echo "Fetching latest image count from input" + if [ -n "${{ github.event.inputs.base64TestList }}" ]; then + echo "Base64-ed Test Input provided, ignoring latest image count" + else + image_count="${{ github.event.inputs.latestVersionsNumber }}" + echo "image_count=$image_count" >> $GITHUB_OUTPUT + fi + else + echo "Fetching default latest image count" + image_count=3 + echo "image_count=$image_count" >> $GITHUB_OUTPUT + fi + echo "Will use following latest image count: $image_count" + check-ecr-images-exist: + name: Check images used as test dependencies exist in ECR + if: always() && needs.should-run.outputs.should_run == 'true' environment: integration permissions: id-token: write contents: read - name: Check images used as test dependencies exist in ECR + needs: [should-run] runs-on: ubuntu-latest strategy: fail-fast: false @@ -49,12 +263,14 @@ jobs: page_size: ${{matrix.mirror.page_size}} build-chainlink: + if: always() && needs.should-run.outputs.should_run == 'true' environment: integration permissions: id-token: write contents: read name: Build Chainlink Image runs-on: ubuntu-latest + needs: [should-run, select-versions] steps: - name: Collect Metrics id: collect-gha-metrics @@ -69,202 +285,310 @@ jobs: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + ref: ${{ needs.select-versions.outputs.chainlink_version }} - name: Build Chainlink Image uses: ./.github/actions/build-chainlink-image with: tag_suffix: "" dockerfile: core/chainlink.Dockerfile - git_commit_sha: ${{ github.sha }} + git_commit_sha: ${{ needs.select-versions.outputs.chainlink_version }} + check_image_exists: 'true' AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + get-latest-available-images: + name: Get Latest EVM Implementation's Images + if: always() && needs.should-run.outputs.should_run == 'true' + environment: integration + runs-on: ubuntu-latest + needs: [check-ecr-images-exist, should-run, select-versions] + permissions: + id-token: write + contents: read + env: + LATEST_IMAGE_COUNT: ${{ needs.select-versions.outputs.latest_image_count }} + outputs: + geth_images: ${{ env.GETH_IMAGES }} + nethermind_images: ${{ env.NETHERMIND_IMAGES }} + besu_images: ${{ env.BESU_IMAGES }} + erigon_images: ${{ env.ERIGON_IMAGES }} + steps: + # Setup AWS creds + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + aws-region: ${{ secrets.QA_AWS_REGION }} + role-to-assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + role-duration-seconds: 3600 + # Login to ECR + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 + with: + mask-password: "true" + env: + AWS_REGION: ${{ secrets.QA_AWS_REGION }} + # ecrimagefetcher is a tool to get latest images from ECR + - name: Set Up ecrimagefetcher + shell: bash + run: | + go install github.com/smartcontractkit/chainlink-testing-framework/tools/ecrimagefetcher@v1.0.1 + - name: Get latest docker images from ECR + if: ${{ github.event.inputs.base64TestList == '' }} + env: + AWS_REGION: ${{ secrets.QA_AWS_REGION }} + ETH_IMPLEMENTATIONS: ${{ needs.select-versions.outputs.evm_implementations }} + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + if [[ "$ETH_IMPLEMENTATIONS" == *"geth"* ]]; then + geth_images=$(ecrimagefetcher 'ethereum/client-go' '^v[0-9]+\.[0-9]+\.[0-9]+$' ${{ env.LATEST_IMAGE_COUNT }}) + echo "GETH_IMAGES=$geth_images" >> $GITHUB_ENV + echo "Geth latest images: $geth_images" + fi + + if [[ "$ETH_IMPLEMENTATIONS" == *"nethermind"* ]]; then + nethermind_images=$(ecrimagefetcher 'nethermind/nethermind' '^[0-9]+\.[0-9]+\.[0-9]+$' ${{ env.LATEST_IMAGE_COUNT }}) + echo "NETHERMIND_IMAGES=$nethermind_images" >> $GITHUB_ENV + echo "Nethermind latest images: $nethermind_images" + fi + + if [[ "$ETH_IMPLEMENTATIONS" == *"besu"* ]]; then + # 24.3.3 is ignored as it doesn't support data & input fields in eth_call + besu_images=$(ecrimagefetcher 'hyperledger/besu' '^[0-9]+\.[0-9]+(\.[0-9]+)?$' ${{ env.LATEST_IMAGE_COUNT }} ">=24.5.1") + echo "BESU_IMAGES=$besu_images" >> $GITHUB_ENV + echo "Besu latest images: $besu_images" + fi + + if [[ "$ETH_IMPLEMENTATIONS" == *"erigon"* ]]; then + # 2.60.0 and 2.60.1 are ignored as they stopped working with CL node + erigon_images=$(ecrimagefetcher 'thorax/erigon' '^v[0-9]+\.[0-9]+\.[0-9]+$' ${{ env.LATEST_IMAGE_COUNT }} "> $GITHUB_ENV + echo "Erigon latest images: $erigon_images" + fi + # End Build Test Dependencies - client-compatibility-matrix: + prepare-compatibility-matrix: + name: Prepare Compatibility Matrix + if: always() && needs.should-run.outputs.should_run == 'true' environment: integration permissions: checks: write pull-requests: write id-token: write contents: read - needs: [build-chainlink, check-ecr-images-exist] + needs: [get-latest-available-images,should-run,select-versions] + runs-on: ubuntu-latest + env: + ETH_IMPLEMENTATIONS: ${{ needs.select-versions.outputs.evm_implementations }} + BASE64_TEST_LIST: ${{ github.event.inputs.base64TestList }} + outputs: + matrix: ${{ env.JOB_MATRIX_JSON }} + steps: + - name: Decode Base64 Test List Input if Set + if: env.BASE64_TEST_LIST != '' + run: | + echo "Decoding base64 tests list from the input" + DECODED_BASE64_TEST_LIST=$(echo $BASE64_TEST_LIST | base64 -d) + echo "Decoded input:" + echo "$DECODED_BASE64_TEST_LIST" + is_valid=$(echo "$DECODED_BASE64_TEST_LIST" | jq . > /dev/null 2>&1; echo $?) + if [ "$is_valid" -ne 0 ]; then + echo "Invalid base64 input. Please provide a valid base64 encoded JSON list of tests." + echo "Here is an example of valid JSON:" + cat <> $GITHUB_ENV + # testlistgenerator is a tool that builds a matrix of tests to run + - name: Set Up testlistgenerator + if: env.BASE64_TEST_LIST == '' + shell: bash + run: | + go install github.com/smartcontractkit/chainlink-testing-framework/tools/testlistgenerator@v1.1.0 + - name: Prepare matrix input + if: env.BASE64_TEST_LIST == '' + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + if [[ "$ETH_IMPLEMENTATIONS" == *"geth"* ]]; then + echo "Will test compatibility with geth" + testlistgenerator -o compatibility_test_list.json -p cron -r TestCronBasic -f './smoke/cron_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p flux -r TestFluxBasic -f './smoke/flux_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p runlog -r TestRunLogBasic -f './smoke/runlog_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p log_poller -r TestLogPollerFewFiltersFixedDepth -f './smoke/log_poller_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr -r TestOCRBasic -f './smoke/ocr_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr2 -r '^TestOCRv2Basic/plugins$' -f './smoke/ocr2_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p automation -r 'TestAutomationBasic/registry_2_1_logtrigger' -f './smoke/automation_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p keeper -r 'TestKeeperBasicSmoke/registry_1_3' -f './smoke/keeper_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrf -r '^TestVRFBasic/Request_Randomness$' -f './smoke/vrf_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrfv2 -r '^TestVRFv2Basic/Request_Randomness$' -f './smoke/vrfv2_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrfv2plus -r '^TestVRFv2Plus$/^Link_Billing$' -f './smoke/vrfv2plus_test.go' -e geth -d "${{ needs.get-latest-available-images.outputs.geth_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + else + echo "Will not test compatibility with geth" + fi + + if [[ "$ETH_IMPLEMENTATIONS" == *"besu"* ]]; then + echo "Will test compatibility with besu" + testlistgenerator -o compatibility_test_list.json -p cron -r TestCronBasic -f './smoke/cron_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p flux -r TestFluxBasic -f './smoke/flux_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p runlog -r TestRunLogBasic -f './smoke/runlog_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p log_poller -r TestLogPollerFewFiltersFixedDepth -f './smoke/log_poller_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr -r TestOCRBasic -f './smoke/ocr_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr2 -r '^TestOCRv2Basic/plugins$' -f './smoke/ocr2_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p automation -r 'TestAutomationBasic/registry_2_1_logtrigger' -f './smoke/automation_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p keeper -r 'TestKeeperBasicSmoke/registry_1_3' -f './smoke/keeper_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrf -r '^TestVRFBasic/Request_Randomness$' -f './smoke/vrf_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + # VRFv2 and VRFV2Plus tests are disabled for besu until the functionalities they rely on are supported + # testlistgenerator -o compatibility_test_list.json -p vrfv2 -r '^TestVRFv2Basic/Request_Randomness$' -f './smoke/vrfv2_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + # testlistgenerator -o compatibility_test_list.json -p vrfv2plus -r '^TestVRFv2Plus$/^Link_Billing$' -f './smoke/vrfv2plus_test.go' -e besu -d "${{ needs.get-latest-available-images.outputs.besu_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + else + echo "Will not test compatibility with besu" + fi + + if [[ "$ETH_IMPLEMENTATIONS" == *"erigon"* ]]; then + echo "Will test compatibility with erigon" + testlistgenerator -o compatibility_test_list.json -p cron -r TestCronBasic -f './smoke/cron_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p flux -r TestFluxBasic -f './smoke/flux_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p runlog -r TestRunLogBasic -f './smoke/runlog_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p log_poller -r TestLogPollerFewFiltersFixedDepth -f './smoke/log_poller_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr -r TestOCRBasic -f './smoke/ocr_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr2 -r '^TestOCRv2Basic/plugins$' -f './smoke/ocr2_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p automation -r 'TestAutomationBasic/registry_2_1_logtrigger' -f './smoke/automation_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p keeper -r 'TestKeeperBasicSmoke/registry_1_3' -f './smoke/keeper_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrf -r '^TestVRFBasic/Request_Randomness$' -f './smoke/vrf_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrfv2 -r '^TestVRFv2Basic/Request_Randomness$' -f './smoke/vrfv2_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrfv2plus -r '^TestVRFv2Plus$/^Link_Billing$' -f './smoke/vrfv2plus_test.go' -e erigon -d "${{ needs.get-latest-available-images.outputs.erigon_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + else + echo "Will not test compatibility with erigon" + fi + + if [[ "$ETH_IMPLEMENTATIONS" == *"nethermind"* ]]; then + echo "Will test compatibility with nethermind" + testlistgenerator -o compatibility_test_list.json -p cron -r TestCronBasic -f './smoke/cron_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p flux -r TestFluxBasic -f './smoke/flux_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p runlog -r TestRunLogBasic -f './smoke/runlog_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p log_poller -r TestLogPollerFewFiltersFixedDepth -f './smoke/log_poller_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr -r TestOCRBasic -f './smoke/ocr_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p ocr2 -r '^TestOCRv2Basic/plugins$' -f './smoke/ocr2_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p automation -r 'TestAutomationBasic/registry_2_1_logtrigger' -f './smoke/automation_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p keeper -r 'TestKeeperBasicSmoke/registry_1_3' -f './smoke/keeper_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + testlistgenerator -o compatibility_test_list.json -p vrf -r '^TestVRFBasic/Request_Randomness$' -f './smoke/vrf_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + # VRFv2 and VRFV2Plus tests are disabled for nethermind until the functionalities they rely on are supported + # testlistgenerator -o compatibility_test_list.json -p vrfv2 -r '^TestVRFv2Basic/Request_Randomness$' -f './smoke/vrfv2_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + # testlistgenerator -o compatibility_test_list.json -p vrfv2plus -r '^TestVRFv2Plus$/^Link_Billing$' -f './smoke/vrfv2plus_test.go' -e nethermind -d "${{ needs.get-latest-available-images.outputs.nethermind_images }}" -t "evm-implementation-compatibility-test" -n "ubuntu-latest" + else + echo "Will not test compatibility with nethermind" + fi + + jq . compatibility_test_list.json + JOB_MATRIX_JSON=$(jq -c . compatibility_test_list.json) + echo "JOB_MATRIX_JSON=${JOB_MATRIX_JSON}" >> $GITHUB_ENV + + run-client-compatibility-matrix: + name: ${{ matrix.evm_node.product }} compatibility with ${{ matrix.evm_node.docker_image }} + if: always() && needs.should-run.outputs.should_run == 'true' && needs.build-chainlink.result == 'success' + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + needs: [build-chainlink, prepare-compatibility-matrix, should-run, select-versions] env: SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 - CHAINLINK_COMMIT_SHA: ${{ github.sha }} + CHAINLINK_COMMIT_SHA: ${{ needs.select-versions.outputs.chainlink_version }} CHAINLINK_ENV_USER: ${{ github.actor }} TEST_LOG_LEVEL: debug strategy: fail-fast: false matrix: - include: - - name: ocr-geth - os: ubuntu-latest - test: TestOCRBasic - file: ocr - client: geth - timeout: 30m - pyroscope_env: ci-smoke-ocr-geth-simulated - - name: ocr-nethermind - test: TestOCRBasic - file: ocr - client: nethermind - timeout: 30m - pyroscope_env: ci-smoke-ocr-nethermind-simulated - - name: ocr-besu - test: TestOCRBasic - file: ocr - client: besu - timeout: 30m - pyroscope_env: ci-smoke-ocr-besu-simulated - - name: ocr-erigon - test: TestOCRBasic - file: ocr - client: erigon - timeout: 30m - pyroscope_env: ci-smoke-ocr-erigon-simulated - - name: ocr2-geth - test: "^TestOCRv2Basic/plugins$" - file: ocr2 - client: geth - timeout: 30m - pyroscope_env: ci-smoke-ocr2-geth-simulated - - name: ocr2-nethermind - test: "^TestOCRv2Basic/plugins$" - file: ocr2 - client: nethermind - timeout: 30m - pyroscope_env: ci-smoke-nethermind-evm-simulated - - name: ocr2-besu - test: "^TestOCRv2Basic/plugins$" - file: ocr2 - client: besu - timeout: 30m - pyroscope_env: ci-smoke-ocr2-besu-simulated - - name: ocr2-erigon - test: "^TestOCRv2Basic/plugins$" - file: ocr2 - client: erigon - timeout: 60m - pyroscope_env: ci-smoke-ocr2-erigon-simulated + evm_node: ${{fromJson(needs.prepare-compatibility-matrix.outputs.matrix)}} runs-on: ubuntu-latest - name: Client Compatibility Test ${{ matrix.name }} steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: repository: smartcontractkit/chainlink - ref: ${{ github.sha }} - - name: Prepare Base64 TOML config - env: - RUN_ID: ${{ github.run_id }} - SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 - PYROSCOPE_SERVER: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - PYROSCOPE_ENVIRONMENT: ci-client-compatability-${{ matrix.client }}-testnet - PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - ETH2_EL_CLIENT: ${{matrix.client}} - CHAINLINK_VERSION: ${{ github.sha }} - GRAFANA_URL: "http://localhost:8080/primary" - GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - GRAFANA_BEARER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - LOKI_ENDPOINT: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push - LOKI_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - LOKI_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + ref: ${{ needs.select-versions.outputs.chainlink_version }} + - name: Setup GAP for Grafana + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 + with: + # aws inputs + aws-region: ${{ secrets.AWS_REGION }} + aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} + api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + # other inputs + duplicate-authorization-header: "true" + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ needs.select-versions.outputs.chainlink_version }} + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: "http://localhost:8080/primary" + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + ethExecutionClient: ${{ matrix.evm_node.eth_implementation }} + customEthClientDockerImage: ${{ matrix.evm_node.docker_image }} + pyroscopeServer: ${{ secrets.QA_PYROSCOPE_INSTANCE }} + pyroscopeEnvironment: ci-client-compatability-${{ matrix.eth_client }}-testnet + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + - name: Prepare test log name run: | - convert_to_toml_array() { - local IFS=',' - local input_array=($1) - local toml_array_format="[" - - for element in "${input_array[@]}"; do - toml_array_format+="\"$element\"," - done - - toml_array_format="${toml_array_format%,}]" - echo "$toml_array_format" - } + replace_special_chars() { + if [ -z "$1" ]; then + echo "Please provide a string as an argument." + return 1 + fi - selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS") + local input_string="$1" - if [ -n "$ETH2_EL_CLIENT" ]; then - execution_layer="$ETH2_EL_CLIENT" - else - execution_layer="geth" - fi - - if [ -n "$PYROSCOPE_SERVER" ]; then - pyroscope_enabled=true - else - pyroscope_enabled=false - fi + # Replace '/' with '-' + local modified_string="${input_string//\//-}" - grafana_bearer_token="" - if [ -n "$GRAFANA_BEARER_TOKEN" ]; then - grafana_bearer_token="bearer_token_secret=\"$GRAFANA_BEARER_TOKEN\"" - fi + # Replace ':' with '-' + modified_string="${modified_string//:/-}" - cat << EOF > config.toml - [Network] - selected_networks=$selected_networks - - [ChainlinkImage] - image="$CHAINLINK_IMAGE" - version="$CHAINLINK_VERSION" - - [Pyroscope] - enabled=$pyroscope_enabled - server_url="$PYROSCOPE_SERVER" - environment="$PYROSCOPE_ENVIRONMENT" - key_secret="$PYROSCOPE_KEY" - - [Logging] - run_id="$RUN_ID" - - [Logging.LogStream] - log_targets=["file","loki"] - - [Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_ENDPOINT" - basic_auth_secret="$LOKI_BASIC_AUTH" - - [Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="$GRAFANA_DASHBOARD_URL" - $grafana_bearer_token - - [PrivateEthereumNetwork] - ethereum_version="eth2" - consensus_layer="prysm" - execution_layer="$execution_layer" - wait_for_finalization=false - - [PrivateEthereumNetwork.EthereumChainConfig] - chain_id=1337 - genesis_delay=15 - seconds_per_slot=3 - validator_count=8 - slots_per_epoch=2 - addresses_to_fund=["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"] - EOF + # Replace '.' with '-' + modified_string="${modified_string//./-}" - BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CONFIG_OVERRIDE - echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV - touch .root_dir + echo "$modified_string" + } + echo "TEST_LOG_NAME=$(replace_special_chars "${{ matrix.evm_node.product }}-${{ matrix.evm_node.docker_image }}-test-logs")" >> $GITHUB_ENV - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: - test_command_to_run: cd ./integration-tests/smoke && go test -timeout ${{ matrix.timeout }} -count=1 -json -test.run ${{ matrix.test }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs + test_command_to_run: cd ./integration-tests && touch .root_dir && go test -timeout 30m -count=1 -json ${{ matrix.evm_node.run }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ github.sha }} + cl_image_tag: ${{ needs.select-versions.outputs.chainlink_version }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - artifacts_name: ${{ matrix.name }}-test-logs + artifacts_name: ${{ env.TEST_LOG_NAME }} artifacts_location: | ./integration-tests/smoke/logs/ /tmp/gotest.log - publish_check_name: ${{ matrix.name }} + publish_check_name: ${{ matrix.evm_node.product }}-${{ matrix.evm_node.eth_implementation }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} @@ -281,7 +605,7 @@ jobs: start-slack-thread: name: Start Slack Thread - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} + if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' environment: integration outputs: thread_ts: ${{ steps.slack.outputs.thread_ts }} @@ -291,7 +615,7 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: [client-compatibility-matrix] + needs: [run-client-compatibility-matrix, should-run, select-versions] steps: - name: Debug Result run: echo ${{ join(needs.*.result, ',') }} @@ -310,7 +634,7 @@ jobs: "type": "header", "text": { "type": "plain_text", - "text": "Client Compatability Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", + "text": "EVM Implementation Compatibility Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", "emoji": true } }, @@ -328,7 +652,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" + "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ needs.select-versions.outputs.chainlink_version }}|${{ needs.select-versions.outputs.chainlink_version }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" } } ] @@ -338,9 +662,95 @@ jobs: env: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + parse-test-results: + name: Parse Test Results + if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + runs-on: ubuntu-latest + needs: [run-client-compatibility-matrix,should-run] + outputs: + base64_parsed_results: ${{ steps.get-test-results.outputs.base64_parsed_results }} + steps: + # workflowresultparser is a tool to get job results from a workflow run + - name: Set Up workflowresultparser + shell: bash + run: | + go install github.com/smartcontractkit/chainlink-testing-framework/tools/workflowresultparser@v1.0.0 + - name: Get and parse Test Results + shell: bash + id: get-test-results + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^automation compatibility with (.*?)$" -namedKey="automation" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^keeper compatibility with (.*?)$" -namedKey="keeper" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^log_poller compatibility with (.*?)$" -namedKey="log_poller" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^ocr compatibility with (.*?)$" -namedKey="ocr" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^ocr2 compatibility with (.*?)$" -namedKey="ocr2" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^vrf compatibility with (.*?)$" -namedKey="vrf" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^vrfv2 compatibility with (.*?)$" -namedKey="vrfv2" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^vrfv2plus compatibility with (.*?)$" -namedKey="vrfv2plus" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^flux compatibility with (.*?)$" -namedKey="flux" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^runlog compatibility with (.*?)$" -namedKey="runlog" -outputFile=output.json + workflowresultparser -workflowRunID ${{ github.run_id }} -githubToken ${{ github.token }} -githubRepo "${{ github.repository }}" -jobNameRegex "^cron compatibility with (.*?)$" -namedKey="cron" -outputFile=output.json + + echo "base64_parsed_results=$(base64 -w 0 output.json)" >> $GITHUB_OUTPUT + + display-test-results: + name: Aggregated test results + if: always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' && needs.parse-test-results.result == 'success' + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + runs-on: ubuntu-latest + needs: [start-slack-thread, should-run, select-versions, parse-test-results] + steps: + # asciitable is a tool that prints results in a nice ASCII table + - name: Set Up asciitable + shell: bash + run: | + go install github.com/smartcontractkit/chainlink-testing-framework/tools/asciitable@v1.0.2 + - name: Print aggregated test results + shell: bash + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + raw_results="$(echo ${{ needs.parse-test-results.outputs.base64_parsed_results }} | base64 -d)" + echo $raw_results > input.json + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "automation" --namedKey "automation" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "keeper" --namedKey "keeper" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "log_poller" --namedKey "log_poller" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "ocr" --namedKey "ocr" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "ocr2" --namedKey "ocr2" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "vrf" --namedKey "vrf" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "vrfv2" --namedKey "vrfv2" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "vrfv2plus" --namedKey "vrfv2plus" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "flux" --namedKey "flux" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "cron" --namedKey "cron" + asciitable --firstColumn "EVM Implementation" --secondColumn Result --jsonfile input.json --outputFile output.txt --section "runlog" --namedKey "runlog" + + echo + echo "AGGREGATED RESULTS" + cat output.txt + + echo "## Aggregated EVM Implementations compatibility results summary" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cat output.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + post-test-results-to-slack: name: Post Test Results for ${{matrix.product}} - if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} + if: ${{ always() && needs.*.result != 'skipped' && needs.*.result != 'cancelled' && needs.should-run.outputs.should_run == 'true' }} environment: integration permissions: checks: write @@ -348,24 +758,38 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - needs: start-slack-thread + needs: [start-slack-thread, should-run, parse-test-results] strategy: fail-fast: false matrix: - product: [ocr, ocr2] + product: [automation, keeper, log_poller, ocr, ocr2, vrf, vrfv2, vrfv2plus, cron, flux, runlog] steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: - ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + ref: ${{ needs.select-versions.outputs.chainlink_version }} + - name: Get test results for ${{ matrix.product }} + id: get-product-results + shell: bash + run: | + raw_results="$(echo ${{ needs.parse-test-results.outputs.base64_parsed_results }} | base64 -d)" + product_result=$(echo "$raw_results" | jq -c "select(has(\"${{ matrix.product }}\")) | .${{ matrix.product }}[]") + if [ -n "$product_result" ]; then + base64_result=$(echo $product_result | base64 -w 0) + echo "base64_result=$base64_result" >> $GITHUB_OUTPUT + else + echo "No results found for ${{ matrix.product }}" + echo "base64_result=" >> $GITHUB_OUTPUT + fi - name: Post Test Results to Slack uses: ./.github/actions/notify-slack-jobs-result with: github_token: ${{ github.token }} github_repository: ${{ github.repository }} workflow_run_id: ${{ github.run_id }} - github_job_name_regex: ^Client Compatibility Test ${{ matrix.product }}-(?.*?)$ + github_job_name_regex: ^${{ matrix.product }} compatibility with (.*?)$ message_title: ${{ matrix.product }} slack_channel_id: ${{ secrets.QA_SLACK_CHANNEL }} slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} + base64_parsed_results: ${{ steps.get-product-results.outputs.base64_result }} diff --git a/.github/workflows/evm-version-compatibility-tests.yml b/.github/workflows/evm-version-compatibility-tests.yml deleted file mode 100644 index 09ef1da26b..0000000000 --- a/.github/workflows/evm-version-compatibility-tests.yml +++ /dev/null @@ -1,340 +0,0 @@ -#name: EVM Node Version Compatibility Tests -#on: -# merge_group: -# pull_request: -# push: -# tags: -# - "*" -# workflow_dispatch: -# inputs: -# base64_test_list: -# description: Base64 encoded test list (same format as ./integration-tests/evm_node_compatibility_test_list.json) -# required: false -# type: string -# -#env: -# CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink -# INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com -# MOD_CACHE_VERSION: 2 -# -#jobs: -# -# # Check if go.mod has changed -# check-dependency-bump: -# runs-on: ubuntu-latest -# outputs: -# dependency_changed: ${{ steps.changes.outputs.dependency_changed }} -# steps: -# - name: Checkout code -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# with: -# fetch-depth: 0 -# - name: Check for go.mod changes -# id: changes -# run: | -# git fetch origin ${{ github.base_ref }} -# # if no match is found then grep exits with code 1, but if there is a match it exits with code 0 -# DEPENDENCY_CHANGED=$(git diff origin/${{ github.base_ref }}...HEAD -- go.mod | grep -q 'github.com/ethereum/go-ethereum'; echo $?) -# PR_VERSION=$(grep 'github.com/ethereum/go-ethereum' go.mod | awk '{print $2}') -# -# # here 0 means a match was found, 1 means no match was found -# if [ "$DEPENDENCY_CHANGED" -eq 0 ]; then -# # Dependency was changed in the PR, now compare with the base branch -# git fetch origin ${{ github.base_ref }} -# BASE_VERSION=$(git show origin/${{ github.base_ref }}:go.mod | grep 'github.com/ethereum/go-ethereum' | awk '{print $2}') -# -# echo "Base branch version: $BASE_VERSION" -# echo "PR branch version: $PR_VERSION" -# -# echo "Dependency version changed in the PR compared to the base branch." -# echo "dependency_changed=true" >> $GITHUB_OUTPUT -# else -# echo "No changes to ethereum/go-ethereum dependency in the PR." -# echo "PR branch version: $PR_VERSION" -# echo "dependency_changed=false" >> $GITHUB_OUTPUT -# fi -# -# # Build Test Dependencies -# -# build-chainlink: -# if: needs.check-dependency-bump.outputs.dependency_changed == 'true' || github.event_name == 'workflow_dispatch' -# needs: [check-dependency-bump] -# environment: integration -# permissions: -# id-token: write -# contents: read -# name: Build Chainlink Image -# runs-on: ubuntu-latest -# steps: -# - name: Collect Metrics -# id: collect-gha-metrics -# uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 -# with: -# id: evm-build-chainlink -# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} -# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} -# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} -# this-job-name: Build Chainlink Image -# continue-on-error: true -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# with: -# ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} -# - name: Build Chainlink Image -# uses: ./.github/actions/build-chainlink-image -# with: -# tag_suffix: "" -# dockerfile: core/chainlink.Dockerfile -# git_commit_sha: ${{ github.sha }} -# AWS_REGION: ${{ secrets.QA_AWS_REGION }} -# AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} -# -# build-tests: -# if: needs.check-dependency-bump.outputs.dependency_changed == 'true' || github.event_name == 'workflow_dispatch' -# needs: [check-dependency-bump] -# environment: integration -# permissions: -# id-token: write -# contents: read -# name: Build Tests Binary -# runs-on: ubuntu-latest -# steps: -# - name: Collect Metrics -# id: collect-gha-metrics -# uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 -# with: -# id: evm-build-tests -# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} -# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} -# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} -# this-job-name: Build Tests Binary -# continue-on-error: true -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# with: -# ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} -# - name: Build Tests -# uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/build-tests@7882cf348cd6a1f6bcf1ee8280185584ebba96e9 # v2.3.10 -# with: -# test_download_vendor_packages_command: cd ./integration-tests && go mod download -# token: ${{ secrets.GITHUB_TOKEN }} -# go_mod_path: ./integration-tests/go.mod -# go_tags: embed -# cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} -# cache_restore_only: "true" -# binary_name: tests -# -# build-test-matrix: -# if: needs.check-dependency-bump.outputs.dependency_changed == 'true' || github.event_name == 'workflow_dispatch' -# needs: [check-dependency-bump] -# runs-on: ubuntu-latest -# name: Build Test Matrix -# outputs: -# matrix: ${{ env.JOB_MATRIX_JSON }} -# steps: -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# - name: Setup environment variables -# run: | -# echo "BASE64_TEST_LIST=${{ github.event.inputs.base64_test_list }}" >> $GITHUB_ENV -# - name: Decode Base64 Test List Input if Set -# id: decode-base64-test-list -# if: env.BASE64_TEST_LIST != '' -# run: | -# echo "Decoding base64 test list..." -# DECODED_BASE64_TEST_LIST=$(echo $BASE64_TEST_LIST | base64 -d) -# echo $DECODED_BASE64_TEST_LIST -# cd ./integration-tests -# echo $DECODED_BASE64_TEST_LIST >> ./evm_node_compatibility_test_list.json -# - name: Override Test List If Present -# if: env.BASE64_TEST_LIST == '' -# id: build-test-matrix-list -# run: | -# cd ./integration-tests -# cp ./smoke/evm_node_compatibility_test_list.json . -# - name: Create Test Matrix -# id: create-test-matrix-list -# run: | -# cd ./integration-tests -# JOB_MATRIX_JSON=$(./scripts/buildEvmClientTestMatrixList.sh ./evm_node_compatibility_test_list.json ubuntu-latest) -# echo "JOB_MATRIX_JSON=${JOB_MATRIX_JSON}" >> $GITHUB_ENV -# echo $JOB_MATRIX_JSON | jq . -# -# # End Build Test Dependencies -# -# evm-node-compatiblity-matrix: -# environment: integration -# permissions: -# checks: write -# pull-requests: write -# id-token: write -# contents: read -# needs: -# [check-dependency-bump, build-chainlink, build-tests, build-test-matrix] -# env: -# SELECTED_NETWORKS: SIMULATED -# CHAINLINK_COMMIT_SHA: ${{ github.sha }} -# CHAINLINK_ENV_USER: ${{ github.actor }} -# TEST_LOG_LEVEL: debug -# strategy: -# fail-fast: false -# matrix: -# evm_node: ${{fromJson(needs.build-test-matrix.outputs.matrix)}} -# runs-on: ${{ matrix.evm_node.os }} -# name: EVM node compatibility of ${{ matrix.evm_node.product }} with ${{ matrix.evm_node.docker_image }} -# steps: -# - name: Collect Metrics -# if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' -# id: collect-gha-metrics -# uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 -# with: -# id: evm-e2e-compatability-tests-${{ matrix.evm_node.name }} -# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} -# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} -# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} -# this-job-name: EVM node compatibility ${{ matrix.evm_node.name }} ${{ matrix.evm_node.docker_image }} -# test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' -# continue-on-error: true -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# with: -# ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} -# - name: Build Go Test Command -# id: build-go-test-command -# run: | -# # if the matrix.evm_node.run is set, use it for a different command -# if [ "${{ matrix.evm_node.run }}" != "" ]; then -# echo "run_command=${{ matrix.evm_node.run }} ./smoke/${{ matrix.evm_node.product }}_test.go" >> "$GITHUB_OUTPUT" -# else -# echo "run_command=./smoke/${{ matrix.evm_node.product }}_test.go" >> "$GITHUB_OUTPUT" -# fi -# - name: Prepare Base64 TOML override -# uses: ./.github/actions/setup-create-base64-config -# with: -# runId: ${{ github.run_id }} -# testLogCollect: ${{ vars.TEST_LOG_COLLECT }} -# selectedNetworks: ${{ env.SELECTED_NETWORKS }} -# chainlinkImage: ${{ env.CHAINLINK_IMAGE }} -# chainlinkVersion: ${{ github.sha }} -# lokiEndpoint: ${{ secrets.LOKI_URL }} -# lokiTenantId: ${{ vars.LOKI_TENANT_ID }} -# lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} -# logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} -# grafanaUrl: ${{ vars.GRAFANA_URL }} -# grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" -# ethExecutionClient: ${{ matrix.evm_node.eth_client }} -# customEthClientDockerImage: ${{ matrix.evm_node.docker_image }} -# -# - name: Run Tests -# uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@7882cf348cd6a1f6bcf1ee8280185584ebba96e9 # v2.3.10 -# with: -# test_command_to_run: cd ./integration-tests && go test -timeout 45m -count=1 -json -test.parallel=2 ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestfmt -# test_download_vendor_packages_command: cd ./integration-tests && go mod download -# cl_repo: ${{ env.CHAINLINK_IMAGE }} -# cl_image_tag: ${{ github.sha }} -# aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} -# artifacts_location: ./integration-tests/smoke/logs/ -# publish_check_name: ${{ matrix.evm_node.product }}-compatibility-${{ matrix.evm_node.eth_client }}-${{ matrix.evm_node.docker_image }} -# token: ${{ secrets.GITHUB_TOKEN }} -# go_mod_path: ./integration-tests/go.mod -# cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} -# cache_restore_only: "true" -# QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} -# QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} -# QA_KUBECONFIG: "" -# should_tidy: "false" -# - name: Print failed test summary -# if: always() -# uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@7882cf348cd6a1f6bcf1ee8280185584ebba96e9 # v2.3.10 -# -# start-slack-thread: -# name: Start Slack Thread -# if: ${{ always() && needs.check-dependency-bump.outputs.dependency_changed == 'true' && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} -# environment: integration -# outputs: -# thread_ts: ${{ steps.slack.outputs.thread_ts }} -# permissions: -# checks: write -# pull-requests: write -# id-token: write -# contents: read -# runs-on: ubuntu-latest -# needs: [ evm-node-compatiblity-matrix] -# steps: -# - name: Debug Result -# run: echo ${{ join(needs.*.result, ',') }} -# - name: Main Slack Notification -# uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 -# id: slack -# with: -# channel-id: ${{ secrets.QA_SLACK_CHANNEL }} -# payload: | -# { -# "attachments": [ -# { -# "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || '#2E7D32' }}", -# "blocks": [ -# { -# "type": "header", -# "text": { -# "type": "plain_text", -# "text": "EVM Node Compatability Test Results ${{ contains(join(needs.*.result, ','), 'failure') && ':x:' || ':white_check_mark:'}}", -# "emoji": true -# } -# }, -# { -# "type": "section", -# "text": { -# "type": "mrkdwn", -# "text": "${{ contains(join(needs.*.result, ','), 'failure') && 'Some tests failed, notifying <@U060CGGPY8H>' || 'All Good!' }}" -# } -# }, -# { -# "type": "divider" -# }, -# { -# "type": "section", -# "text": { -# "type": "mrkdwn", -# "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" -# } -# } -# ] -# } -# ] -# } -# env: -# SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} -# -# post-test-results-to-slack: -# name: Post Test Results for ${{matrix.evm_node.eth_client}} to Slack -# if: ${{ always() && needs.check-dependency-bump.outputs.dependency_changed == 'true' && needs.*.result != 'skipped' && needs.*.result != 'cancelled' }} -# environment: integration -# permissions: -# checks: write -# pull-requests: write -# id-token: write -# contents: read -# runs-on: ubuntu-latest -# needs: [start-slack-thread, build-test-matrix] -# strategy: -# fail-fast: false -# matrix: -# # this basically works as group by in SQL; we should update it when we update the test list JSON file -# product: [automation,ocr,ocr2,vrf,vrfv2,vrfv2plus] -# steps: -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# with: -# ref: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha }} -# - name: Post Test Results to Slack -# uses: ./.github/actions/notify-slack-jobs-result -# with: -# github_token: ${{ github.token }} -# github_repository: ${{ github.repository }} -# workflow_run_id: ${{ github.run_id }} -# github_job_name_regex: ^EVM node compatibility of ${{ matrix.product }} with (?.*?)$ -# message_title: ${{ matrix.product }} -# slack_channel_id: ${{ secrets.QA_SLACK_CHANNEL }} -# slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} -# slack_thread_ts: ${{ needs.start-slack-thread.outputs.thread_ts }} diff --git a/.github/workflows/gha-workflow-validation.yml b/.github/workflows/gha-workflow-validation.yml index 6b8f8ac4f8..a265a4eef3 100644 --- a/.github/workflows/gha-workflow-validation.yml +++ b/.github/workflows/gha-workflow-validation.yml @@ -14,14 +14,14 @@ jobs: runs-on: ubuntu-latest steps: - name: GHA Workflow Validator - uses: smartcontractkit/.github/actions/gha-workflow-validator@01a5f5e0228b46dbedd9ad4b4dda062cb89bb3d9 # gha-workflow-validator@0.1.2 + uses: smartcontractkit/.github/actions/gha-workflow-validator@d316f66b2990ea4daa479daa3de6fc92b00f863e # gha-workflow-validator@0.2.0 env: GITHUB_TOKEN: ${{ github.token }} - name: Collect Metrics if: always() id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 with: id: lint-gh-workflows org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} diff --git a/.github/workflows/integration-tests-publish.yml b/.github/workflows/integration-tests-publish.yml index 1eee375c33..7a842fef6f 100644 --- a/.github/workflows/integration-tests-publish.yml +++ b/.github/workflows/integration-tests-publish.yml @@ -1,4 +1,4 @@ -name: Integration Tests Publish +name: Test Image Publish # Publish the compiled integration tests on: push: diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 733234f036..7231fed2f7 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -166,7 +166,7 @@ jobs: - name: Lint Go uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 with: - version: v1.55.2 + version: v1.59.1 # We already cache these directories in setup-go skip-pkg-cache: true skip-build-cache: true @@ -246,11 +246,161 @@ jobs: with: repository: smartcontractkit/ccip ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} - - name: Build Test Image + - name: Build Go Test Command + id: build-go-test-command + run: | + # if the matrix.product.run is set, use it for a different command + if [ "${{ matrix.product.run }}" != "" ]; then + echo "run_command=${{ matrix.product.run }} ./smoke/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" + else + echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" + fi + - name: Setup GAP for Grafana + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 + with: + # aws inputs + aws-region: ${{ secrets.AWS_REGION }} + aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} + api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + # other inputs + duplicate-authorization-header: "true" + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ inputs.evm-ref || github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: "http://localhost:8080/primary" # This is GAP's address + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + + ## Run this step when changes that require tests to be run are made + - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: ./.github/actions/build-test-image + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: "" + should_tidy: "false" + go_coverage_src_dir: /var/tmp/go-coverage + go_coverage_dest_dir: ${{ github.workspace }}/.covdata + + - name: Upload Coverage Data + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + timeout-minutes: 2 + continue-on-error: true + with: + name: cl-node-coverage-data-${{ matrix.product.name }} + path: .covdata + retention-days: 1 + + - name: Print failed test summary + if: always() + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + + eth-smoke-tests-matrix-log-poller: + if: ${{ !(contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') || github.event_name == 'workflow_dispatch') || inputs.distinct_run_name != '' }} + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + needs: + [build-chainlink, changes, compare-tests, build-lint-integration-tests] + env: + SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 + CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} + CHAINLINK_ENV_USER: ${{ github.actor }} + TEST_LOG_LEVEL: debug + strategy: + fail-fast: false + matrix: + product: ${{fromJson(needs.compare-tests.outputs.lp-matrix)}} + runs-on: ${{ matrix.product.os }} + name: ETH Smoke Tests ${{ matrix.product.name }} + steps: + - name: Collect Metrics + if: needs.changes.outputs.src == 'true' + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: ${{ env.COLLECTION_ID }}-matrix-${{ matrix.product.name }} + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: ETH Smoke Tests ${{ matrix.product.name }} + test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + repository: smartcontractkit/chainlink + ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Build Go Test Command + id: build-go-test-command + run: | + # if the matrix.product.run is set, use it for a different command + if [ "${{ matrix.product.run }}" != "" ]; then + echo "run_command=${{ matrix.product.run }} ./smoke/${{ matrix.product.file }}_test.go" >> "$GITHUB_OUTPUT" + else + echo "run_command=./smoke/${{ matrix.product.name }}_test.go" >> "$GITHUB_OUTPUT" + fi + - name: Setup GAP for Grafana + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 + with: + # aws inputs + aws-region: ${{ secrets.AWS_REGION }} + aws-role-arn: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} + api-gateway-host: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + # other inputs + duplicate-authorization-header: "true" + - name: Prepare Base64 TOML override + uses: ./.github/actions/setup-create-base64-config + with: + runId: ${{ github.run_id }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} + selectedNetworks: ${{ env.SELECTED_NETWORKS }} + chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + chainlinkVersion: ${{ inputs.evm-ref || github.sha }} + pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + pyroscopeEnvironment: ${{ matrix.product.pyroscope_env }} + pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} + lokiEndpoint: https://${{ secrets.GRAFANA_INTERNAL_HOST }}/loki/api/v1/push + lokiTenantId: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + lokiBasicAuth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} + grafanaUrl: "http://localhost:8080/primary" # This is GAP's address + grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} + ## Run this step when changes that require tests to be run are made + - name: Run Tests + if: needs.changes.outputs.src == 'true' + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 + with: + test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs + test_download_vendor_packages_command: cd ./integration-tests && go mod download + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ inputs.evm-ref || github.sha }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: ${{ matrix.product.name }}-test-logs + artifacts_location: | + ./integration-tests/smoke/logs/ + /tmp/gotest.log + publish_check_name: ${{ matrix.product.name }} + token: ${{ secrets.GITHUB_TOKEN }} + go_mod_path: ./integration-tests/go.mod + cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} + cache_restore_only: "true" QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} @@ -265,7 +415,7 @@ jobs: contents: read needs: [build-chainlink, changes, build-lint-integration-tests] env: - SELECTED_NETWORKS: SIMULATED,SIMULATED_1,SIMULATED_2 + SELECTED_NETWORKS: SIMULATED CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} CHAINLINK_ENV_USER: ${{ github.actor }} TEST_LOG_LEVEL: debug @@ -353,6 +503,13 @@ jobs: nodes: 2 os: ubuntu-latest file: ocr + pyroscope_env: ci-smoke-ocr-evm-simulated + - name: reorg_above_finality + id: reorg_above_finality + nodes: 1 + os: ubuntu-latest + file: reorg_above_finality + pyroscope_env: ci-smoke-reorg-above-finality-evm-simulated - name: ocr2 id: ocr2 nodes: 6 @@ -481,7 +638,7 @@ jobs: echo "base_64_override=$(base64 -w 0 -i ${{ matrix.product.config_path }})" >> "$GITHUB_OUTPUT" fi - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -531,7 +688,7 @@ jobs: ## Run this step when changes that require tests to be run are made - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 env: BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} @@ -570,7 +727,7 @@ jobs: # Run this step when changes that do not need the test to run are made - name: Run Setup if: needs.changes.outputs.src == 'false' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_download_vendor_packages_command: cd ./integration-tests && go mod download go_mod_path: ./integration-tests/go.mod @@ -774,7 +931,7 @@ jobs: grafanaUrl: ${{ vars.GRAFANA_URL }} grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Migration Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_command_to_run: cd ./integration-tests && go test -timeout 20m -count=1 -json ./migration 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs test_download_vendor_packages_command: cd ./integration-tests && go mod download @@ -812,3 +969,305 @@ jobs: with: channel-id: "#team-test-tooling-internal" slack-message: ":x: :mild-panic-intensifies: Node Migration Tests Failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" + + ## Solana Section + get_solana_sha: + # We don't directly merge dependabot PRs, so let's not waste the resources + if: ${{ github.actor != 'dependabot[bot]' && inputs.run_solana != 'false' }} + name: Get Solana Sha From Go Mod + environment: Integration + runs-on: ubuntu-latest + outputs: + sha: ${{ steps.getsha.outputs.sha }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + repository: smartcontractkit/chainlink + ref: ${{ inputs.cl_ref || github.event.pull_request.head.sha || github.event.merge_group.head_sha }} + - name: Setup Go + uses: ./.github/actions/setup-go + with: + only-modules: "true" + - name: Get the sha from go mod + id: getshortsha + run: | + sol_ver=$(go list -m -json github.com/smartcontractkit/chainlink-solana | jq -r .Version) + if [ -z "${sol_ver}" ]; then + echo "Error: could not get the solana version from the go.mod file, look above for error(s)" + exit 1 + fi + short_sha="${sol_ver##*-}" + echo "short sha is: ${short_sha}" + echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT" + - name: Checkout solana + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + repository: smartcontractkit/chainlink-solana + ref: develop + fetch-depth: 0 + path: solanapath + - name: Get long sha + id: getsha + run: | + cd solanapath + full_sha=$(git rev-parse ${{steps.getshortsha.outputs.short_sha}}) + if [ -z "${full_sha}" ]; then + echo "Error: could not get the full sha from the short sha using git, look above for error(s)" + exit 1 + fi + echo "sha is: ${full_sha}" + echo "sha=${full_sha}" >> "$GITHUB_OUTPUT" + + get_projectserum_version: + name: Get ProjectSerum Version + environment: integration + runs-on: ubuntu-latest + needs: [get_solana_sha] + outputs: + projectserum_version: ${{ steps.psversion.outputs.projectserum_version }} + steps: + - name: Checkout the solana repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + repository: smartcontractkit/chainlink-solana + ref: ${{ needs.get_solana_sha.outputs.sha }} + - name: Get ProjectSerum Version + id: psversion + uses: smartcontractkit/chainlink-solana/.github/actions/projectserum_version@4b971869e26b79c7ce3fb7c98005cc2e3f350915 # stable action on Oct 12 2022 + + solana-test-image-exists: + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + name: Check If Solana Test Image Exists + runs-on: ubuntu-latest + needs: [get_solana_sha] + outputs: + exists: ${{ steps.check-image.outputs.exists }} + steps: + - name: Check if image exists + id: check-image + uses: smartcontractkit/chainlink-github-actions/docker/image-exists@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + with: + repository: chainlink-solana-tests + tag: ${{ needs.get_solana_sha.outputs.sha }} + AWS_REGION: ${{ secrets.QA_AWS_REGION }} + AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + + solana-build-contracts: + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + name: Solana Build Artifacts + runs-on: ubuntu22.04-16cores-64GB + needs: + [ + changes, + get_projectserum_version, + solana-test-image-exists, + get_solana_sha, + ] + steps: + - name: Collect Metrics + if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: ${{ env.COLLECTION_ID }}-solana-build-contracts + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Solana Build Artifacts + continue-on-error: true + - name: Checkout the solana repo + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + repository: smartcontractkit/chainlink-solana + ref: ${{ needs.get_solana_sha.outputs.sha }} + - name: Build contracts + if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + uses: smartcontractkit/chainlink-solana/.github/actions/build_contract_artifacts@46b1311a5a83f33d08ffa8e1e0ab04f9ad51665d # node20 update on may 10, 2024 + with: + ref: ${{ needs.get_solana_sha.outputs.sha }} + image: projectserum/build + image-version: ${{ needs.get_projectserum_version.outputs.projectserum_version }} + + solana-build-test-image: + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + name: Solana Build Test Image + runs-on: ubuntu22.04-16cores-64GB + needs: + [ + solana-build-contracts, + solana-test-image-exists, + changes, + get_solana_sha, + ] + env: + CONTRACT_ARTIFACTS_PATH: contracts/target/deploy + steps: + - name: Collect Metrics + if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: ${{ env.COLLECTION_ID }}-solana-build-test-image + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Solana Build Test Image + continue-on-error: true + - name: Checkout the repo + if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + repository: smartcontractkit/chainlink-solana + ref: ${{ needs.get_solana_sha.outputs.sha }} + - name: Build Test Image + if: (needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' + uses: ./.github/actions/build-test-image + with: + tag: ${{ needs.get_solana_sha.outputs.sha }} + artifacts_path: ${{ env.CONTRACT_ARTIFACTS_PATH }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + - run: echo "this exists so we don't have to run anything else if the build is skipped" + if: needs.changes.outputs.src == 'false' || needs.solana-test-image-exists.outputs.exists == 'true' + + solana-smoke-tests: + if: ${{ !contains(join(github.event.pull_request.labels.*.name, ' '), 'skip-smoke-tests') }} + environment: integration + permissions: + checks: write + pull-requests: write + id-token: write + contents: read + name: Solana Smoke Tests + runs-on: ubuntu22.04-16cores-64GB + needs: + [ + build-chainlink, + solana-build-contracts, + solana-build-test-image, + changes, + get_solana_sha, + ] + env: + CHAINLINK_COMMIT_SHA: ${{ inputs.evm-ref || github.sha }} + CHAINLINK_ENV_USER: ${{ github.actor }} + TEST_LOG_LEVEL: debug + CONTRACT_ARTIFACTS_PATH: contracts/target/deploy + steps: + - name: Collect Metrics + if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: ${{ env.COLLECTION_ID }}-solana-e2e-tests + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Solana Smoke Tests + test-results-file: '{"testType":"go","filePath":"/tmp/gotest.log"}' + continue-on-error: true + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + repository: smartcontractkit/chainlink-solana + ref: ${{ needs.get_solana_sha.outputs.sha }} + - name: Run Setup + if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/setup-run-tests-environment@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 + with: + go_mod_path: ./integration-tests/go.mod + cache_restore_only: true + cache_key_id: core-solana-e2e-${{ env.MOD_CACHE_VERSION }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} + dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} + - name: Pull Artifacts + if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + run: | + IMAGE_NAME=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} + # Pull the Docker image + docker pull "$IMAGE_NAME" + + # Create a container without starting it + CONTAINER_ID=$(docker create "$IMAGE_NAME") + + # Copy the artifacts from the container + mkdir -p ./${{env.CONTRACT_ARTIFACTS_PATH}}/ + docker cp "$CONTAINER_ID:/go/testdir/${{env.CONTRACT_ARTIFACTS_PATH}}/" "./${{env.CONTRACT_ARTIFACTS_PATH}}/../" + + # Remove the created container + docker rm "$CONTAINER_ID" + - name: Install Solana CLI # required for ensuring the local test validator is configured correctly + run: ./scripts/install-solana-ci.sh + - name: Install gauntlet + run: | + yarn --cwd ./gauntlet install --frozen-lockfile + yarn --cwd ./gauntlet build + yarn --cwd ./gauntlet gauntlet + - name: Generate config overrides + run: | # https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md + cat << EOF > config.toml + [ChainlinkImage] + image="${{ env.CHAINLINK_IMAGE }}" + version="${{ inputs.evm-ref || github.sha }}" + [Common] + user="${{ github.actor }}" + internal_docker_repo = "${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com" + EOF + # shellcheck disable=SC2002 + BASE64_CONFIG_OVERRIDE=$(cat config.toml | base64 -w 0) + # shellcheck disable=SC2086 + echo ::add-mask::$BASE64_CONFIG_OVERRIDE + # shellcheck disable=SC2086 + echo "BASE64_CONFIG_OVERRIDE=$BASE64_CONFIG_OVERRIDE" >> $GITHUB_ENV + - name: Run Tests + if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 + with: + test_command_to_run: export ENV_JOB_IMAGE=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} && make test_smoke + cl_repo: ${{ env.CHAINLINK_IMAGE }} + cl_image_tag: ${{ inputs.evm-ref || github.sha }} + publish_check_name: Solana Smoke Test Results + go_mod_path: ./integration-tests/go.mod + cache_key_id: core-solana-e2e-${{ env.MOD_CACHE_VERSION }} + token: ${{ secrets.GITHUB_TOKEN }} + aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: solana-test-logs + artifacts_location: | + ./integration-tests/smoke/logs + /tmp/gotest.log + QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} + QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} + QA_KUBECONFIG: "" + run_setup: false + go_coverage_src_dir: /var/tmp/go-coverage + go_coverage_dest_dir: ${{ github.workspace }}/.covdata + + - name: Upload Coverage Data + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + timeout-minutes: 2 + continue-on-error: true + with: + name: cl-node-coverage-data-solana-tests + path: .covdata + retention-days: 1 diff --git a/.github/workflows/live-testnet-tests.yml b/.github/workflows/live-testnet-tests.yml index 667c8a2074..760f70b60e 100644 --- a/.github/workflows/live-testnet-tests.yml +++ b/.github/workflows/live-testnet-tests.yml @@ -213,7 +213,7 @@ jobs: github_token: ${{ github.token }} github_repository: ${{ github.repository }} workflow_run_id: ${{ github.run_id }} - github_job_name_regex: ^${{ matrix.network }} (?.*?) Tests$ + github_job_name_regex: ^${{ matrix.network }} (.*?) Tests$ message_title: ${{ matrix.network }} slack_channel_id: ${{ secrets.QA_SLACK_CHANNEL }} slack_bot_token: ${{ secrets.QA_SLACK_API_KEY }} @@ -248,7 +248,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -331,7 +331,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -414,7 +414,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -497,7 +497,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -576,7 +576,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -659,7 +659,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -742,7 +742,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -825,7 +825,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -904,7 +904,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -983,7 +983,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} @@ -1062,7 +1062,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} diff --git a/.github/workflows/live-vrf-tests.yml b/.github/workflows/live-vrf-tests.yml index 745d7db19f..89c62c104f 100644 --- a/.github/workflows/live-vrf-tests.yml +++ b/.github/workflows/live-vrf-tests.yml @@ -139,7 +139,7 @@ jobs: with: fetch-depth: 0 - name: Setup GAP for Grafana - uses: smartcontractkit/.github/actions/setup-gap@main + uses: smartcontractkit/.github/actions/setup-gap@d316f66b2990ea4daa479daa3de6fc92b00f863e # setup-gap@0.3.2 with: # aws inputs aws-region: ${{ secrets.AWS_REGION }} diff --git a/.github/workflows/on-demand-keeper-smoke-tests.yml b/.github/workflows/on-demand-keeper-smoke-tests.yml index 452c8478d0..facd90c823 100644 --- a/.github/workflows/on-demand-keeper-smoke-tests.yml +++ b/.github/workflows/on-demand-keeper-smoke-tests.yml @@ -151,7 +151,7 @@ jobs: ## Run this step when changes that require tests to be run are made - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs test_download_vendor_packages_command: cd ./integration-tests && go mod download @@ -287,4 +287,4 @@ jobs: go test -run=NonExistentTest ./smoke/... || echo "ignore expected test failure" go_mod_path: ./integration-tests/go.mod cache_key_id: core-e2e-${{ env.MOD_CACHE_VERSION }} - cache_restore_only: "false" \ No newline at end of file + cache_restore_only: "false" diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index 9c29c021b8..ae24786b43 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -2,6 +2,19 @@ name: On Demand OCR Soak Test on: workflow_dispatch: inputs: + testToRun: + description: Select a test to run + required: true + default: TestOCRSoak + type: choice + options: + - TestOCRSoak + - TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled + - TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled + - TestOCRSoak_GasSpike + - TestOCRSoak_ChangeBlockGasLimit + - TestOCRSoak_RPCDownForAllCLNodes + - TestOCRSoak_RPCDownForHalfCLNodes base64Config: description: base64-ed config required: true @@ -73,7 +86,7 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 env: DETACH_RUNNER: true TEST_SUITE: soak @@ -83,7 +96,7 @@ jobs: TEST_UPLOAD_CPU_PROFILE: true TEST_UPLOAD_MEM_PROFILE: true with: - test_command_to_run: cd ./integration-tests && go test -v -count=1 -run ^TestOCRSoak$ ./soak + test_command_to_run: cd ./integration-tests && go test -v -count=1 -run ^${{ github.event.inputs.testToRun }}$ ./soak test_download_vendor_packages_command: make gomod cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ env.CHAINLINK_VERSION }} diff --git a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml index beed388e3f..03b07ab1b1 100644 --- a/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml +++ b/.github/workflows/on-demand-vrfv2-eth2-clients-test.yml @@ -46,7 +46,7 @@ jobs: echo "### Execution client used" >>$GITHUB_STEP_SUMMARY echo "\`${{ env.ETH2_EL_CLIENT }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run TestVRFv2Basic ./smoke/vrfv2_test.go 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs test_download_vendor_packages_command: cd ./integration-tests && go mod download diff --git a/.github/workflows/on-demand-vrfv2-performance-test.yml b/.github/workflows/on-demand-vrfv2-performance-test.yml index 79711a107b..43899b4e57 100644 --- a/.github/workflows/on-demand-vrfv2-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2-performance-test.yml @@ -76,7 +76,7 @@ jobs: echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2 test_download_vendor_packages_command: cd ./integration-tests && go mod download diff --git a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml index c2469d488d..242eed2364 100644 --- a/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-eth2-clients-test.yml @@ -46,7 +46,7 @@ jobs: echo "### Execution client used" >>$GITHUB_STEP_SUMMARY echo "\`${{ env.ETH2_EL_CLIENT }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -run ^TestVRFv2Plus$/^Link_Billing$ ./smoke/vrfv2plus_test.go 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs test_download_vendor_packages_command: cd ./integration-tests && go mod download diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml index 2ee3256b53..fa915381d1 100644 --- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml @@ -76,7 +76,7 @@ jobs: echo "### Networks on which test was run" >>$GITHUB_STEP_SUMMARY echo "\`${{ env.NETWORKS }}\`" >>$GITHUB_STEP_SUMMARY - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@af92c5fae8dcf1659201e907db82d221fc304b94 # v2.3.21 with: test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2plus test_download_vendor_packages_command: cd ./integration-tests && go mod download diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml index 0115397a46..3136847922 100644 --- a/.github/workflows/pr-labels.yml +++ b/.github/workflows/pr-labels.yml @@ -19,7 +19,7 @@ jobs: - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 with: - version: ^8.0.0 + version: ^9.0.0 - uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 with: diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 30e07ec189..4dfe3cbb49 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -220,7 +220,7 @@ jobs: - name: Collect Metrics id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 with: id: ccip-solidity-publish-beta org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} @@ -263,7 +263,7 @@ jobs: - name: Collect Metrics id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 with: id: ccip-solidity-publish-prod org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} diff --git a/.gitignore b/.gitignore index eeb2209d36..816bb085da 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ tools/clroot/db.sqlite3-wal *.iml debug.env *.txt +operator_ui/install # codeship *.aes diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e3d87871cb..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "contracts/foundry-lib/forge-std"] - path = contracts/foundry-lib/forge-std - url = https://github.com/foundry-rs/forge-std \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 3834400ba6..7155cff2d5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -16,6 +16,9 @@ linters: - depguard - whitespace - containedctx + - fatcontext + - mirror + - loggercheck linters-settings: exhaustive: default-signifies-exhaustive: true @@ -31,8 +34,30 @@ linters-settings: # - G304 # - G404 govet: - # report about shadowed variables - check-shadowing: true + enable: + - shadow + settings: + printf: + # Additionally check chainlink custom loggers + funcs: + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracef + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infof + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicf + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalf + - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infof + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationf + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracef + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalf errorlint: # Allow formatting of errors without %w errorf: false @@ -113,6 +138,28 @@ linters-settings: desc: Use gopkg.in/guregu/null.v4 instead - pkg: github.com/go-gorm/gorm desc: Use github.com/jmoiron/sqlx directly instead + loggercheck: + # Check that *w logging functions have even number of args (i.e., well formed key-value pairs). + rules: + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracew + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infow + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicw + - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalw + - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infow + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracew + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalw + - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).With issues: exclude-rules: - path: test diff --git a/.tool-versions b/.tool-versions index ebf563134e..ca10fd5f6a 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,9 +1,9 @@ golang 1.21.7 mockery 2.42.2 nodejs 20.13.1 -pnpm 8.15.8 +pnpm 9.4.0 postgres 15.1 helm 3.10.3 zig 0.11.0 -golangci-lint 1.55.2 +golangci-lint 1.59.1 protoc 25.1 diff --git a/GNUmakefile b/GNUmakefile index 638ff9e036..4db64002f6 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -82,7 +82,7 @@ docker-plugins: .PHONY: operator-ui operator-ui: ## Fetch the frontend - go generate ./core/web + go run operator_ui/install.go . .PHONY: abigen abigen: ## Build & install abigen. @@ -114,7 +114,11 @@ setup-testdb: ## Setup the test database. testdb: ## Prepares the test database. go run . local db preparetest -.PHONY: testdb +.PHONY: testdb-force +testdb-force: ## Prepares the test database, drops any pesky user connections that stand in the the way. + go run . local db preparetest --force + +.PHONY: testdb-user-only testdb-user-only: ## Prepares the test database with user only. go run . local db preparetest --user-only @@ -127,7 +131,7 @@ presubmit: ## Format go files and imports. .PHONY: gomods gomods: ## Install gomods - go install github.com/jmank88/gomods@v0.1.0 + go install github.com/jmank88/gomods@v0.1.1 .PHONY: mockery mockery: $(mockery) ## Install mockery. @@ -158,7 +162,7 @@ config-docs: ## Generate core node configuration documentation .PHONY: golangci-lint golangci-lint: ## Run golangci-lint for all issues. [ -d "./golangci-lint" ] || mkdir ./golangci-lint && \ - docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.56.2 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 > ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt + docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.59.1 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 > ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt GORELEASER_CONFIG ?= .goreleaser.yaml diff --git a/README.md b/README.md index 6d246a6c46..a62be57a6e 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ regarding Chainlink social accounts, news, and networking. 1. [Install Go 1.21](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 v8 via npm](https://pnpm.io/installation#using-npm). +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` 3. Install [Postgres (>= 12.x)](https://wiki.postgresql.org/wiki/Detailed_installation_guides). It is recommended to run the latest major version of postgres. - Note if you are running the official Chainlink docker image, the highest supported Postgres version is 16.x due to the bundled client. @@ -136,7 +136,7 @@ For more information on creating and using external adapters, please see our [ex ### Running tests -1. [Install pnpm via npm](https://pnpm.io/installation#using-npm) +1. [Install pnpm 9 via npm](https://pnpm.io/installation#using-npm) 2. Install [gencodec](https://github.com/fjl/gencodec) and [jq](https://stedolan.github.io/jq/download/) to be able to run `go generate ./...` and `make abigen` @@ -185,6 +185,14 @@ source .dbenv make testdb ``` +If you encounter the error `database accessed by other users (SQLSTATE 55006) exit status 1` +and you want force the database creation then use +``` +source .dbenv +make testdb-force +``` + + 7. Run tests: ```bash diff --git a/common/client/models.go b/common/client/models.go index fd0c391594..8b61613766 100644 --- a/common/client/models.go +++ b/common/client/models.go @@ -18,7 +18,7 @@ const ( InsufficientFunds // Tx was rejected due to insufficient funds. ExceedsMaxFee // Attempt's fee was higher than the node's limit and got rejected. FeeOutOfValidRange // This error is returned when we use a fee price suggested from an RPC, but the network rejects the attempt due to an invalid range(mostly used by L2 chains). Retry by requesting a new suggested fee price. - OutOfCounters // The error returned when a transaction is too complex to be proven by zk circuits. This error is mainly returned by zk chains. + TerminallyStuck // The error returned when a transaction is or could get terminally stuck in the mempool without any chance of inclusion. sendTxReturnCodeLen // tracks the number of errors. Must always be last ) @@ -50,8 +50,8 @@ func (c SendTxReturnCode) String() string { return "ExceedsMaxFee" case FeeOutOfValidRange: return "FeeOutOfValidRange" - case OutOfCounters: - return "OutOfCounters" + case TerminallyStuck: + return "TerminallyStuck" default: return fmt.Sprintf("SendTxReturnCode(%d)", c) } diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 4504b5071e..3076d99b61 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -848,7 +848,7 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { ExpectedTxResult: "not enough keccak counters to continue the execution", ExpectedCriticalErr: "", ResultsByCode: sendTxErrors{ - OutOfCounters: {errors.New("not enough keccak counters to continue the execution")}, + TerminallyStuck: {errors.New("not enough keccak counters to continue the execution")}, }, }, } diff --git a/common/client/poller_test.go b/common/client/poller_test.go index 82a05b5dfc..91af579307 100644 --- a/common/client/poller_test.go +++ b/common/client/poller_test.go @@ -13,6 +13,7 @@ import ( "go.uber.org/zap" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) func Test_Poller(t *testing.T) { @@ -89,7 +90,7 @@ func Test_Poller(t *testing.T) { } return true } - require.Eventually(t, logsSeen, time.Second, time.Millisecond) + require.Eventually(t, logsSeen, tests.WaitTimeout(t), 100*time.Millisecond) }) t.Run("Test polling timeout", func(t *testing.T) { @@ -114,13 +115,14 @@ func Test_Poller(t *testing.T) { logsSeen := func() bool { return observedLogs.FilterMessage("polling error: context deadline exceeded").Len() >= 1 } - require.Eventually(t, logsSeen, time.Second, time.Millisecond) + require.Eventually(t, logsSeen, tests.WaitTimeout(t), 100*time.Millisecond) }) t.Run("Test unsubscribe during polling", func(t *testing.T) { wait := make(chan struct{}) + closeOnce := sync.OnceFunc(func() { close(wait) }) pollFunc := func(ctx context.Context) (Head, error) { - close(wait) + closeOnce() // Block in polling function until context is cancelled if <-ctx.Done(); true { return nil, ctx.Err() @@ -145,7 +147,7 @@ func Test_Poller(t *testing.T) { logsSeen := func() bool { return observedLogs.FilterMessage("polling error: context canceled").Len() >= 1 } - require.Eventually(t, logsSeen, time.Second, time.Millisecond) + require.Eventually(t, logsSeen, tests.WaitTimeout(t), 100*time.Millisecond) }) } diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index 294e922c1c..a9e30ffff1 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -374,7 +374,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Che } } if err != nil { - ec.lggr.Debugw("Batch sending transactions failed", err) + ec.lggr.Debugw("Batch sending transactions failed", "err", err) } var txIDsToUnconfirm []int64 for idx, txErr := range txErrs { @@ -1160,7 +1160,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) For continue } attempt.Tx = *etx // for logging - ec.lggr.Debugw("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", attempt.ChainSpecificFeeLimit, "callerProvidedFeeLimit", etx.FeeLimit, attempt) + ec.lggr.Debugw("Sending transaction", "txAttemptID", attempt.ID, "txHash", attempt.Hash, "err", err, "meta", etx.Meta, "feeLimit", attempt.ChainSpecificFeeLimit, "callerProvidedFeeLimit", etx.FeeLimit, "attempt", attempt) if errCode, err := ec.client.SendTransactionReturnCode(ctx, *etx, attempt, ec.lggr); errCode != client.Successful && err != nil { ec.lggr.Errorw(fmt.Sprintf("ForceRebroadcast: failed to rebroadcast tx %v with sequence %v, gas limit %v, and caller provided fee Limit %v : %s", etx.ID, *etx.Sequence, attempt.ChainSpecificFeeLimit, etx.FeeLimit, err.Error()), "err", err, "fee", attempt.TxFee) continue diff --git a/common/txmgr/mocks/tx_manager.go b/common/txmgr/mocks/tx_manager.go index 974fd45590..502f6fe8a2 100644 --- a/common/txmgr/mocks/tx_manager.go +++ b/common/txmgr/mocks/tx_manager.go @@ -11,6 +11,8 @@ import ( null "gopkg.in/guregu/null.v4" + pkgtypes "github.com/smartcontractkit/chainlink-common/pkg/types" + txmgr "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" @@ -329,6 +331,34 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetFor return r0, r1 } +// GetTransactionStatus provides a mock function with given fields: ctx, transactionID +func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetTransactionStatus(ctx context.Context, transactionID string) (pkgtypes.TransactionStatus, error) { + ret := _m.Called(ctx, transactionID) + + if len(ret) == 0 { + panic("no return value specified for GetTransactionStatus") + } + + var r0 pkgtypes.TransactionStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (pkgtypes.TransactionStatus, error)); ok { + return rf(ctx, transactionID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) pkgtypes.TransactionStatus); ok { + r0 = rf(ctx, transactionID) + } else { + r0 = ret.Get(0).(pkgtypes.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 +} + // HealthReport provides a mock function with given fields: func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) HealthReport() map[string]error { ret := _m.Called() diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 44b518fdaa..3ac0d2e1d6 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -2,7 +2,6 @@ package txmgr import ( "context" - "database/sql" "errors" "fmt" "math/big" @@ -14,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" @@ -29,6 +29,8 @@ import ( // ResumeCallback is assumed to be idempotent type ResumeCallback func(ctx context.Context, id uuid.UUID, result interface{}, err error) error +type NewErrorClassifier func(err error) txmgrtypes.ErrorClassifier + // TxManager is the main component of the transaction manager. // It is also the interface to external callers. // @@ -62,6 +64,7 @@ type TxManager[ FindEarliestUnconfirmedBroadcastTime(ctx context.Context) (nullv4.Time, error) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context) (nullv4.Int, error) CountTransactionsByState(ctx context.Context, state txmgrtypes.TxState) (count uint32, err error) + GetTransactionStatus(ctx context.Context, transactionID string) (state commontypes.TransactionStatus, err error) } type reset struct { @@ -102,13 +105,14 @@ type Txm[ chSubbed chan struct{} wg sync.WaitGroup - reaper *Reaper[CHAIN_ID] - resender *Resender[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] - broadcaster *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] - confirmer *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] - tracker *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] - fwdMgr txmgrtypes.ForwarderManager[ADDR] - txAttemptBuilder txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + reaper *Reaper[CHAIN_ID] + resender *Resender[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] + broadcaster *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + confirmer *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] + tracker *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] + fwdMgr txmgrtypes.ForwarderManager[ADDR] + txAttemptBuilder txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + newErrorClassifier NewErrorClassifier } func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RegisterResumeCallback(fn ResumeCallback) { @@ -141,26 +145,28 @@ func NewTxm[ confirmer *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], resender *Resender[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], tracker *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], + newErrorClassifierFunc NewErrorClassifier, ) *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { b := Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{ - logger: logger.Sugared(lggr), - txStore: txStore, - config: cfg, - txConfig: txCfg, - keyStore: keyStore, - chainID: chainId, - checkerFactory: checkerFactory, - chHeads: make(chan HEAD), - trigger: make(chan ADDR), - chStop: make(chan struct{}), - chSubbed: make(chan struct{}), - reset: make(chan reset), - fwdMgr: fwdMgr, - txAttemptBuilder: txAttemptBuilder, - broadcaster: broadcaster, - confirmer: confirmer, - resender: resender, - tracker: tracker, + logger: logger.Sugared(lggr), + txStore: txStore, + config: cfg, + txConfig: txCfg, + keyStore: keyStore, + chainID: chainId, + checkerFactory: checkerFactory, + chHeads: make(chan HEAD), + trigger: make(chan ADDR), + chStop: make(chan struct{}), + chSubbed: make(chan struct{}), + reset: make(chan reset), + fwdMgr: fwdMgr, + txAttemptBuilder: txAttemptBuilder, + broadcaster: broadcaster, + confirmer: confirmer, + resender: resender, + tracker: tracker, + newErrorClassifier: newErrorClassifierFunc, } if txCfg.ResendAfterThreshold() <= 0 { @@ -498,7 +504,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTran if txRequest.IdempotencyKey != nil { var existingTx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] existingTx, err = b.txStore.FindTxWithIdempotencyKey(ctx, *txRequest.IdempotencyKey, b.chainID) - if err != nil && !errors.Is(err, sql.ErrNoRows) { + if err != nil { return tx, fmt.Errorf("Failed to search for transaction with IdempotencyKey: %w", err) } if existingTx != nil { @@ -525,7 +531,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CreateTran txRequest.ToAddress = txRequest.ForwarderAddress txRequest.EncodedPayload = fwdPayload } else { - b.logger.Errorf("Failed to use forwarder set upstream: %w", fwdErr.Error()) + b.logger.Errorf("Failed to use forwarder set upstream: %v", fwdErr.Error()) } } @@ -625,6 +631,38 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CountTrans return b.txStore.CountTransactionsByState(ctx, state, b.chainID) } +func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetTransactionStatus(ctx context.Context, transactionID string) (status commontypes.TransactionStatus, err error) { + // Loads attempts and receipts in the transaction + tx, err := b.txStore.FindTxWithIdempotencyKey(ctx, transactionID, b.chainID) + if err != nil { + return status, fmt.Errorf("failed to find transaction with IdempotencyKey %s: %w", transactionID, err) + } + // This check is required since a no-rows error returns nil err + if tx == nil { + return status, fmt.Errorf("failed to find transaction with IdempotencyKey %s", transactionID) + } + switch tx.State { + case TxUnconfirmed, TxConfirmedMissingReceipt: + // Return unconfirmed for ConfirmedMissingReceipt since a receipt is required to determine if it is finalized + return commontypes.Unconfirmed, nil + case TxConfirmed: + // TODO: Check for finality and return finalized status + // Return unconfirmed if tx receipt's block is newer than the latest finalized block + return commontypes.Unconfirmed, nil + case TxFatalError: + // Use an ErrorClassifier to determine if the transaction is considered Fatal + txErr := b.newErrorClassifier(tx.GetError()) + if txErr != nil && txErr.IsFatal() { + return commontypes.Fatal, tx.GetError() + } + // Return failed for all other tx's marked as FatalError + return commontypes.Failed, tx.GetError() + default: + // Unstarted and InProgress are classified as unknown since they are not supported by the ChainWriter interface + return commontypes.Unknown, nil + } +} + type NullTxManager[ CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], @@ -708,6 +746,10 @@ func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Cou return count, errors.New(n.ErrMsg) } +func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetTransactionStatus(ctx context.Context, transactionID string) (status commontypes.TransactionStatus, err error) { + return +} + func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) pruneQueueAndCreateTxn( ctx context.Context, txRequest txmgrtypes.TxRequest[ADDR, TX_HASH], diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go index e04ebe9587..d2afbd209d 100644 --- a/common/txmgr/types/tx.go +++ b/common/txmgr/types/tx.go @@ -339,3 +339,10 @@ func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetChecker() (Transm return t, nil } + +// Provides error classification to external components in a chain agnostic way +// Only exposes the error types that could be set in the transaction error field +type ErrorClassifier interface { + error + IsFatal() bool +} diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index 2b82e1f648..c102fb5912 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -53,6 +53,7 @@ type TxStore[ FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) // Find transactions loaded with transaction attempts and receipts by transaction IDs and states FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []TxState, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + FindTxWithIdempotencyKey(ctx context.Context, idempotencyKey string, chainID CHAIN_ID) (tx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) } // TransactionStore contains the persistence layer methods needed to manage Txs and TxAttempts diff --git a/contracts/.changeset/brave-seahorses-shave.md b/contracts/.changeset/brave-seahorses-shave.md new file mode 100644 index 0000000000..3f29e6aa4a --- /dev/null +++ b/contracts/.changeset/brave-seahorses-shave.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +upgrade keystone contracts to 0.8.24 diff --git a/contracts/.changeset/calm-bikes-grin.md b/contracts/.changeset/calm-bikes-grin.md new file mode 100644 index 0000000000..675d42ce4f --- /dev/null +++ b/contracts/.changeset/calm-bikes-grin.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add events, add getter and add comments #bugfix diff --git a/contracts/.changeset/green-pigs-reflect.md b/contracts/.changeset/green-pigs-reflect.md new file mode 100644 index 0000000000..cb197a32bc --- /dev/null +++ b/contracts/.changeset/green-pigs-reflect.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add test for v23 #added diff --git a/contracts/.changeset/new-bugs-draw.md b/contracts/.changeset/new-bugs-draw.md new file mode 100644 index 0000000000..93fba83b55 --- /dev/null +++ b/contracts/.changeset/new-bugs-draw.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/ninety-cobras-drive.md b/contracts/.changeset/ninety-cobras-drive.md new file mode 100644 index 0000000000..cd57662462 --- /dev/null +++ b/contracts/.changeset/ninety-cobras-drive.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +relax pragma solidity version in VRF SubscriptionAPI.sol diff --git a/contracts/.changeset/odd-gorillas-develop.md b/contracts/.changeset/odd-gorillas-develop.md new file mode 100644 index 0000000000..93fba83b55 --- /dev/null +++ b/contracts/.changeset/odd-gorillas-develop.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/proud-seals-draw.md b/contracts/.changeset/proud-seals-draw.md new file mode 100644 index 0000000000..6bda7ed255 --- /dev/null +++ b/contracts/.changeset/proud-seals-draw.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +move v23 contracts #bugfix diff --git a/contracts/.changeset/quiet-crews-impress.md b/contracts/.changeset/quiet-crews-impress.md new file mode 100644 index 0000000000..5310806f1c --- /dev/null +++ b/contracts/.changeset/quiet-crews-impress.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal Use audited version of OCR2Base.sol in OCR3Capability.sol diff --git a/contracts/.changeset/red-wasps-behave.md b/contracts/.changeset/red-wasps-behave.md new file mode 100644 index 0000000000..93fba83b55 --- /dev/null +++ b/contracts/.changeset/red-wasps-behave.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/spicy-mirrors-care.md b/contracts/.changeset/spicy-mirrors-care.md new file mode 100644 index 0000000000..93fba83b55 --- /dev/null +++ b/contracts/.changeset/spicy-mirrors-care.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.changeset/two-doors-dance.md b/contracts/.changeset/two-doors-dance.md new file mode 100644 index 0000000000..93fba83b55 --- /dev/null +++ b/contracts/.changeset/two-doors-dance.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal diff --git a/contracts/.solhintignore b/contracts/.solhintignore index 1fad724b52..ee9b9cf026 100644 --- a/contracts/.solhintignore +++ b/contracts/.solhintignore @@ -22,7 +22,7 @@ ./src/v0.8/automation/AutomationForwarder.sol ./src/v0.8/automation/AutomationForwarderLogic.sol ./src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol -./src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +./src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol # Ignore tests / test helpers (for now) diff --git a/contracts/foundry-lib/forge-std b/contracts/foundry-lib/forge-std deleted file mode 160000 index 978ac6fadb..0000000000 --- a/contracts/foundry-lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 978ac6fadb62f5f0b723c996f64be52eddba6801 diff --git a/contracts/foundry.toml b/contracts/foundry.toml index b5905481c4..1605b3130c 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -74,9 +74,10 @@ evm_version = 'paris' [profile.keystone] optimizer_runs = 1_000_000 -solc_version = '0.8.19' +solc_version = '0.8.24' src = 'src/v0.8/keystone' test = 'src/v0.8/keystone/test' +evm_version = 'paris' [profile.operatorforwarder] optimizer_runs = 1_000_000 diff --git a/contracts/gas-snapshots/keystone.gas-snapshot b/contracts/gas-snapshots/keystone.gas-snapshot index 0cc6650f86..2880e4c0e3 100644 --- a/contracts/gas-snapshots/keystone.gas-snapshot +++ b/contracts/gas-snapshots/keystone.gas-snapshot @@ -1,99 +1,107 @@ -CapabilityRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 152088) -CapabilityRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 176069) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24678) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145679) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94561) -CapabilityRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92916) -CapabilityRegistry_AddDONTest:test_AddDON() (gas: 499044) -CapabilityRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19249) -CapabilityRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 291958) -CapabilityRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 365106) -CapabilityRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 375985) -CapabilityRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 177974) -CapabilityRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43337) -CapabilityRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 306419) -CapabilityRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184267) -CapabilityRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17624) -CapabilityRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18520) -CapabilityRegistry_AddNodesTest:test_AddsNodeInfo() (gas: 355444) -CapabilityRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 355432) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301394) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55229) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24962) -CapabilityRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27724) -CapabilityRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25130) -CapabilityRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27430) -CapabilityRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27069) -CapabilityRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309822) -CapabilityRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 92873) -CapabilityRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 93001) -CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22879) -CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16166) -CapabilityRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 94265) -CapabilityRegistry_GetCapabilitiesTest:test_ExcludesDeprecatedCapabilities() (gas: 122065) -CapabilityRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 58327) -CapabilityRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65704) -CapabilityRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 88473) -CapabilityRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) -CapabilityRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) -CapabilityRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36675) -CapabilityRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38982) -CapabilityRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 59861) -CapabilityRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 71561) -CapabilityRegistry_RemoveDONsTest:test_RemovesDON() (gas: 60696) -CapabilityRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15669) -CapabilityRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16540) -CapabilityRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36069) -CapabilityRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15838) -CapabilityRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 114053) -CapabilityRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 371521) -CapabilityRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 712537) -CapabilityRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 72324) -CapabilityRegistry_RemoveNodesTest:test_RemovesNode() (gas: 74158) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 24871) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18373) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfDON() (gas: 385126) -CapabilityRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18385) -CapabilityRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19406) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 157904) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17826) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 231052) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 241977) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 103722) -CapabilityRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 172410) -CapabilityRegistry_UpdateDONTest:test_UpdatesDON() (gas: 433638) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20583) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20004) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19742) -CapabilityRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15382) -CapabilityRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36903) -CapabilityRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 250725) -CapabilityRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 158858) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35985) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25086) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 27325) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 29206) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27313) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 26996) -CapabilityRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 25560) -CapabilityRegistry_UpdateNodesTest:test_UpdatesNodeInfo() (gas: 158847) -KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2676465) -KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 150738) -KeystoneForwarder_ReportTest:test_RevertWhen_AlreadyProcessed() (gas: 158024) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 111634) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 143377) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 119553) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 98500) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 98757) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 67777) -KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 77819) -KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 78543) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20162) -KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 90143) -KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14511) -KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 90874) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 847644) -KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 2224138) -KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 2365984) -KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) \ No newline at end of file +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154832) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178813) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24723) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145703) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94606) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92961) +CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 372302) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19273) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 169752) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239789) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 249596) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 116890) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43358) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() (gas: 343924) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 180150) +CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184135) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17602) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18498) +CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358448) +CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358414) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301229) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55174) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24895) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27669) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25108) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27408) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27047) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309679) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89807) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89935) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22944) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16231) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91264) +CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135553) +CapabilitiesRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65468) +CapabilitiesRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 64924) +CapabilitiesRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) +CapabilitiesRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) +CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36407) +CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38692) +CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 65288) +CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73533) +CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54761) +CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15647) +CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16550) +CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36122) +CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15816) +CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115151) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287716) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 561023) +CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73376) +CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75211) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25053) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18418) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385369) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18408) +CapabilitiesRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19415) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152914) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17835) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222996) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 232804) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107643) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163357) +CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 371909) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20631) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20052) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19790) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15430) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36937) +CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256157) +CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162059) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35766) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25069) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 27308) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 29219) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27296) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470803) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341084) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 26951) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 25480) +CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162113) +KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 1797755) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 125910) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 127403) +KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 155928) +KeystoneForwarder_ReportTest:test_RevertWhen_AlreadyAttempted() (gas: 152358) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86348) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118486) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94516) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 75930) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 76298) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45585) +KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55292) +KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 56050) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20184) +KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 88057) +KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14533) +KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88788) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114507) +KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1539921) +KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1534476) +KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) +KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10978) +KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10923) +KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18553) +KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 75629) \ No newline at end of file diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index f10261b87c..0a00d843d7 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -20,7 +20,10 @@ const COMPILER_SETTINGS = { subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction( async (_, __, runSuper) => { const paths = await runSuper() - return paths.filter((p: string) => !p.endsWith('.t.sol')) + const noTests = paths.filter((p: string) => !p.endsWith('.t.sol')) + return noTests.filter( + (p: string) => !p.includes('src/v0.8/vendor/forge-std'), + ) }, ) @@ -69,6 +72,13 @@ let config = { version: '0.8.19', settings: COMPILER_SETTINGS, }, + { + version: '0.8.24', + settings: { + ...COMPILER_SETTINGS, + evmVersion: 'paris', + }, + }, ], overrides: { 'src/v0.8/vrf/VRFCoordinatorV2.sol': { @@ -95,6 +105,10 @@ let config = { }, }, }, + 'src/v0.8/automation/AutomationForwarderLogic.sol': { + version: '0.8.19', + settings: COMPILER_SETTINGS, + }, }, }, mocha: { diff --git a/contracts/package.json b/contracts/package.json index 977d6bb282..2bc654d1c3 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -54,6 +54,10 @@ "@ethersproject/logger": "5.0.6" } }, + "engines": { + "node": ">=18", + "pnpm": ">=9" + }, "devDependencies": { "@ethereum-waffle/mock-contract": "^3.4.4", "@ethersproject/abi": "~5.7.0", diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index c84548fb5f..5c1dfecb44 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true @@ -7,182 +7,3591 @@ settings: overrides: '@ethersproject/logger': 5.0.6 -dependencies: - '@arbitrum/nitro-contracts': - specifier: 1.1.1 - version: 1.1.1 - '@arbitrum/token-bridge-contracts': - specifier: 1.1.2 - version: 1.1.2 - '@changesets/changelog-github': - specifier: ^0.5.0 - version: 0.5.0 - '@changesets/cli': - specifier: ~2.27.3 - version: 2.27.3 - '@eth-optimism/contracts': - specifier: 0.6.0 - version: 0.6.0(ethers@5.7.2) - '@openzeppelin/contracts': - specifier: 4.9.3 - version: 4.9.3 - '@openzeppelin/contracts-upgradeable': - specifier: 4.9.3 - version: 4.9.3 - '@scroll-tech/contracts': - specifier: 0.1.0 - version: 0.1.0 - semver: - specifier: ^7.6.2 - version: 7.6.2 - -devDependencies: - '@ethereum-waffle/mock-contract': - specifier: ^3.4.4 - version: 3.4.4 - '@ethersproject/abi': - specifier: ~5.7.0 - version: 5.7.0 - '@ethersproject/bignumber': - specifier: ~5.7.0 - version: 5.7.0 - '@ethersproject/contracts': - specifier: ~5.7.0 - version: 5.7.0 - '@ethersproject/providers': - specifier: ~5.7.2 - version: 5.7.2 - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^1.0.6 - version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3)(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1) - '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.6 - version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1) - '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.9 - version: 1.0.10(hardhat@2.20.1) - '@nomicfoundation/hardhat-verify': - specifier: ^2.0.7 - version: 2.0.7(hardhat@2.20.1) - '@typechain/ethers-v5': - specifier: ^7.2.0 - version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.4.5) - '@typechain/hardhat': - specifier: ^7.0.0 - version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.20.1)(typechain@8.3.2) - '@types/cbor': - specifier: ~5.0.1 - version: 5.0.1 - '@types/chai': - specifier: ^4.3.16 - version: 4.3.16 - '@types/debug': - specifier: ^4.1.12 - version: 4.1.12 - '@types/deep-equal-in-any-order': - specifier: ^1.0.3 - version: 1.0.3 - '@types/mocha': - specifier: ^10.0.6 - version: 10.0.6 - '@types/node': - specifier: ^20.12.12 - version: 20.12.12 - '@typescript-eslint/eslint-plugin': - specifier: ^7.10.0 - version: 7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.10.0 - version: 7.10.0(eslint@8.57.0)(typescript@5.4.5) - abi-to-sol: - specifier: ^0.6.6 - version: 0.6.6 - cbor: - specifier: ^5.2.0 - version: 5.2.0 - chai: - specifier: ^4.3.10 - version: 4.4.1 - debug: - specifier: ^4.3.4 - version: 4.3.4 - deep-equal-in-any-order: - specifier: ^2.0.6 - version: 2.0.6 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) - ethers: - specifier: ~5.7.2 - version: 5.7.2 - hardhat: - specifier: ~2.20.1 - version: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) - hardhat-abi-exporter: - specifier: ^2.10.1 - version: 2.10.1(hardhat@2.20.1) - hardhat-ignore-warnings: - specifier: ^0.2.6 - version: 0.2.11 - husky: - specifier: ^9.0.11 - version: 9.0.11 - lint-staged: - specifier: ^15.2.2 - version: 15.2.2 - moment: - specifier: ^2.30.1 - version: 2.30.1 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - prettier-plugin-solidity: - specifier: ^1.3.1 - version: 1.3.1(prettier@3.2.5) - solhint: - specifier: ^5.0.1 - version: 5.0.1 - solhint-plugin-chainlink-solidity: - specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1 - version: github.com/smartcontractkit/chainlink-solhint-rules/1b4c0c2663fcd983589d4f33a2e73908624ed43c - solhint-plugin-prettier: - specifier: ^0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) - typechain: - specifier: ^8.2.1 - version: 8.3.2(typescript@5.4.5) - typescript: - specifier: ^5.4.5 - version: 5.4.5 +importers: + + .: + dependencies: + '@arbitrum/nitro-contracts': + specifier: 1.1.1 + version: 1.1.1 + '@arbitrum/token-bridge-contracts': + specifier: 1.1.2 + version: 1.1.2 + '@changesets/changelog-github': + specifier: ^0.5.0 + version: 0.5.0 + '@changesets/cli': + specifier: ~2.27.3 + version: 2.27.3 + '@eth-optimism/contracts': + specifier: 0.6.0 + version: 0.6.0(ethers@5.7.2) + '@openzeppelin/contracts': + specifier: 4.9.3 + version: 4.9.3 + '@openzeppelin/contracts-upgradeable': + specifier: 4.9.3 + version: 4.9.3 + '@scroll-tech/contracts': + specifier: 0.1.0 + version: 0.1.0 + semver: + specifier: ^7.6.2 + version: 7.6.2 + devDependencies: + '@ethereum-waffle/mock-contract': + specifier: ^3.4.4 + version: 3.4.4 + '@ethersproject/abi': + specifier: ~5.7.0 + version: 5.7.0 + '@ethersproject/bignumber': + specifier: ~5.7.0 + version: 5.7.0 + '@ethersproject/contracts': + specifier: ~5.7.0 + version: 5.7.0 + '@ethersproject/providers': + specifier: ~5.7.2 + version: 5.7.2 + '@nomicfoundation/hardhat-chai-matchers': + specifier: ^1.0.6 + version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)))(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + '@nomicfoundation/hardhat-ethers': + specifier: ^3.0.6 + version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + '@nomicfoundation/hardhat-network-helpers': + specifier: ^1.0.9 + version: 1.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + '@nomicfoundation/hardhat-verify': + specifier: ^2.0.7 + version: 2.0.7(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + '@typechain/ethers-v5': + specifier: ^7.2.0 + version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) + '@typechain/hardhat': + specifier: ^7.0.0 + version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))(typechain@8.3.2(typescript@5.4.5)) + '@types/cbor': + specifier: ~5.0.1 + version: 5.0.1 + '@types/chai': + specifier: ^4.3.16 + version: 4.3.16 + '@types/debug': + specifier: ^4.1.12 + version: 4.1.12 + '@types/deep-equal-in-any-order': + specifier: ^1.0.3 + version: 1.0.3 + '@types/mocha': + specifier: ^10.0.6 + version: 10.0.6 + '@types/node': + specifier: ^20.12.12 + version: 20.12.12 + '@typescript-eslint/eslint-plugin': + specifier: ^7.10.0 + version: 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': + specifier: ^7.10.0 + version: 7.10.0(eslint@8.57.0)(typescript@5.4.5) + abi-to-sol: + specifier: ^0.6.6 + version: 0.6.6 + cbor: + specifier: ^5.2.0 + version: 5.2.0 + chai: + specifier: ^4.3.10 + version: 4.4.1 + debug: + specifier: ^4.3.4 + version: 4.3.4(supports-color@8.1.1) + deep-equal-in-any-order: + specifier: ^2.0.6 + version: 2.0.6 + eslint: + specifier: ^8.57.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.0) + eslint-plugin-prettier: + specifier: ^5.1.3 + version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) + ethers: + specifier: ~5.7.2 + version: 5.7.2 + hardhat: + specifier: ~2.20.1 + version: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat-abi-exporter: + specifier: ^2.10.1 + version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + hardhat-ignore-warnings: + specifier: ^0.2.6 + version: 0.2.11 + husky: + specifier: ^9.0.11 + version: 9.0.11 + lint-staged: + specifier: ^15.2.2 + version: 15.2.2 + moment: + specifier: ^2.30.1 + version: 2.30.1 + prettier: + specifier: ^3.2.5 + version: 3.2.5 + prettier-plugin-solidity: + specifier: ^1.3.1 + version: 1.3.1(prettier@3.2.5) + solhint: + specifier: ^5.0.1 + version: 5.0.1 + solhint-plugin-chainlink-solidity: + specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1 + version: '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c' + solhint-plugin-prettier: + specifier: ^0.1.0 + version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) + typechain: + specifier: ^8.2.1 + version: 8.3.2(typescript@5.4.5) + typescript: + specifier: ^5.4.5 + version: 5.4.5 + +packages: + + '@aashutoshrathi/word-wrap@1.2.6': + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + + '@arbitrum/nitro-contracts@1.1.1': + resolution: {integrity: sha512-4Tyk3XVHz+bm8UujUC78LYSw3xAxyYvBCxfEX4z3qE4/ww7Qck/rmce5gbHMzQjArEAzAP2YSfYIFuIFuRXtfg==} + + '@arbitrum/token-bridge-contracts@1.1.2': + resolution: {integrity: sha512-k7AZXiB2HFecJ1KfaDBqgOKe3Loo1ttGLC7hUOVB+0YrihIR6cYpJRuqKSKK4YCy+FF21AUDtaG3x57OFM667Q==} + + '@babel/code-frame@7.18.6': + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.19.1': + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.18.6': + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.24.0': + resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} + engines: {node: '>=6.9.0'} + + '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c': + resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c} + version: 1.2.0 + + '@changesets/apply-release-plan@7.0.1': + resolution: {integrity: sha512-aPdSq/R++HOyfEeBGjEe6LNG8gs0KMSyRETD/J2092OkNq8mOioAxyKjMbvVUdzgr/HTawzMOz7lfw339KnsCA==} + + '@changesets/assemble-release-plan@6.0.0': + resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + + '@changesets/changelog-git@0.2.0': + resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} + + '@changesets/changelog-github@0.5.0': + resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} + + '@changesets/cli@2.27.3': + resolution: {integrity: sha512-ve/VpWApILlSs8cr0okNx5C2LKRawI9XZgvfmf58S8sar2nhx5DPJREFXYZBahs0FeTfvH0rdVl+nGe8QF45Ig==} + hasBin: true + + '@changesets/config@3.0.0': + resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.0.0': + resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + + '@changesets/get-github-info@0.6.0': + resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} + + '@changesets/get-release-plan@4.0.0': + resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.0': + resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + + '@changesets/logger@0.1.0': + resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + + '@changesets/parse@0.4.0': + resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} + + '@changesets/pre@2.0.0': + resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + + '@changesets/read@0.6.0': + resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.0.0': + resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} + + '@changesets/write@0.3.1': + resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.10.0': + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.0': + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eth-optimism/contracts@0.6.0': + resolution: {integrity: sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w==} + peerDependencies: + ethers: ^5 + + '@eth-optimism/core-utils@0.12.0': + resolution: {integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==} + + '@ethereum-waffle/mock-contract@3.4.4': + resolution: {integrity: sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA==} + engines: {node: '>=10.0'} + + '@ethersproject/abi@5.7.0': + resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} + + '@ethersproject/abstract-provider@5.7.0': + resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + + '@ethersproject/abstract-signer@5.7.0': + resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} + + '@ethersproject/address@5.7.0': + resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} + + '@ethersproject/base64@5.7.0': + resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + + '@ethersproject/basex@5.7.0': + resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} + + '@ethersproject/bignumber@5.7.0': + resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + + '@ethersproject/bytes@5.7.0': + resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + + '@ethersproject/constants@5.7.0': + resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + + '@ethersproject/contracts@5.7.0': + resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} + + '@ethersproject/hash@5.7.0': + resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} + + '@ethersproject/hdnode@5.7.0': + resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} + + '@ethersproject/json-wallets@5.7.0': + resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} + + '@ethersproject/keccak256@5.7.0': + resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + + '@ethersproject/logger@5.0.6': + resolution: {integrity: sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==} + + '@ethersproject/networks@5.7.1': + resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + + '@ethersproject/pbkdf2@5.7.0': + resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} + + '@ethersproject/properties@5.7.0': + resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + + '@ethersproject/providers@5.7.2': + resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} + + '@ethersproject/random@5.7.0': + resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} + + '@ethersproject/rlp@5.7.0': + resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + + '@ethersproject/sha2@5.7.0': + resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} + + '@ethersproject/signing-key@5.7.0': + resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} + + '@ethersproject/solidity@5.7.0': + resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==} + + '@ethersproject/strings@5.7.0': + resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + + '@ethersproject/transactions@5.7.0': + resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} + + '@ethersproject/units@5.7.0': + resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} + + '@ethersproject/wallet@5.7.0': + resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} + + '@ethersproject/web@5.7.1': + resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} + + '@ethersproject/wordlists@5.7.0': + resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + + '@jridgewell/resolve-uri@3.1.1': + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@metamask/eth-sig-util@4.0.1': + resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} + engines: {node: '>=12.0.0'} + + '@noble/hashes@1.1.2': + resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} + + '@noble/secp256k1@1.6.3': + resolution: {integrity: sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nomicfoundation/ethereumjs-block@5.0.4': + resolution: {integrity: sha512-AcyacJ9eX/uPEvqsPiB+WO1ymE+kyH48qGGiGV+YTojdtas8itUTW5dehDSOXEEItWGbbzEJ4PRqnQZlWaPvDw==} + engines: {node: '>=18'} + + '@nomicfoundation/ethereumjs-blockchain@7.0.4': + resolution: {integrity: sha512-jYsd/kwzbmpnxx86tXsYV8wZ5xGvFL+7/P0c6OlzpClHsbFzeF41KrYA9scON8Rg6bZu3ZTv6JOAgj3t7USUfg==} + engines: {node: '>=18'} + + '@nomicfoundation/ethereumjs-common@4.0.4': + resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} + + '@nomicfoundation/ethereumjs-ethash@3.0.4': + resolution: {integrity: sha512-xvIrwIMl9sSaiYKRem68+O7vYdj7Q2XWv5P7JXiIkn83918QzWHvqbswTRsH7+r6X1UEvdsURRnZbvZszEjAaQ==} + engines: {node: '>=18'} + + '@nomicfoundation/ethereumjs-evm@2.0.4': + resolution: {integrity: sha512-lTyZZi1KpeMHzaO6cSVisR2tjiTTedjo7PcmhI/+GNFo9BmyY6QYzGeSti0sFttmjbEMioHgXxl5yrLNRg6+1w==} + engines: {node: '>=18'} + + '@nomicfoundation/ethereumjs-rlp@5.0.4': + resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} + engines: {node: '>=18'} + hasBin: true + + '@nomicfoundation/ethereumjs-statemanager@2.0.4': + resolution: {integrity: sha512-HPDjeFrxw6llEi+BzqXkZ+KkvFnTOPczuHBtk21hRlDiuKuZz32dPzlhpRsDBGV1b5JTmRDUVqCS1lp3Gghw4Q==} + peerDependencies: + '@nomicfoundation/ethereumjs-verkle': 0.0.2 + peerDependenciesMeta: + '@nomicfoundation/ethereumjs-verkle': + optional: true + + '@nomicfoundation/ethereumjs-trie@6.0.4': + resolution: {integrity: sha512-3nSwQiFMvr2VFe/aZUyinuohYvtytUqZCUCvIWcPJ/BwJH6oQdZRB42aNFBJ/8nAh2s3OcroWpBLskzW01mFKA==} + engines: {node: '>=18'} + + '@nomicfoundation/ethereumjs-tx@5.0.4': + resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + + '@nomicfoundation/ethereumjs-util@9.0.4': + resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + + '@nomicfoundation/ethereumjs-verkle@0.0.2': + resolution: {integrity: sha512-bjnfZElpYGK/XuuVRmLS3yDvr+cDs85D9oonZ0YUa5A3lgFgokWMp76zXrxX2jVQ0BfHaw12y860n1+iOi6yFQ==} + engines: {node: '>=18'} + + '@nomicfoundation/ethereumjs-vm@7.0.4': + resolution: {integrity: sha512-gsA4IhmtWHI4BofKy3kio9W+dqZQs5Ji5mLjLYxHCkat+JQBUt5szjRKra2F9nGDJ2XcI/wWb0YWUFNgln4zRQ==} + engines: {node: '>=18'} + + '@nomicfoundation/hardhat-chai-matchers@1.0.6': + resolution: {integrity: sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==} + peerDependencies: + '@nomiclabs/hardhat-ethers': ^2.0.0 + chai: ^4.2.0 + ethers: ^5.0.0 + hardhat: ^2.9.4 + + '@nomicfoundation/hardhat-ethers@3.0.6': + resolution: {integrity: sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA==} + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + + '@nomicfoundation/hardhat-network-helpers@1.0.10': + resolution: {integrity: sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==} + peerDependencies: + hardhat: ^2.9.5 + + '@nomicfoundation/hardhat-verify@2.0.7': + resolution: {integrity: sha512-jiYHBX+K6bBN0YhwFHQ5SWWc3dQZliM3pdgpH33C7tnsVACsX1ubZn6gZ9hfwlzG0tyjFM72XQhpaXQ56cE6Ew==} + peerDependencies: + hardhat: ^2.0.4 + + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0': + resolution: {integrity: sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0': + resolution: {integrity: sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0': + resolution: {integrity: sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0': + resolution: {integrity: sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0': + resolution: {integrity: sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0': + resolution: {integrity: sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0': + resolution: {integrity: sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0': + resolution: {integrity: sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0': + resolution: {integrity: sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0': + resolution: {integrity: sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@nomicfoundation/solidity-analyzer@0.1.0': + resolution: {integrity: sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg==} + engines: {node: '>= 12'} + + '@nomiclabs/hardhat-ethers@2.2.3': + resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} + peerDependencies: + ethers: ^5.0.0 + hardhat: ^2.0.0 + + '@offchainlabs/upgrade-executor@1.1.0-beta.0': + resolution: {integrity: sha512-mpn6PHjH/KDDjNX0pXHEKdyv8m6DVGQiI2nGzQn0JbM1nOSHJpWx6fvfjtH7YxHJ6zBZTcsKkqGkFKDtCfoSLw==} + + '@openzeppelin/contracts-upgradeable@4.5.2': + resolution: {integrity: sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==} + + '@openzeppelin/contracts-upgradeable@4.7.3': + resolution: {integrity: sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==} + + '@openzeppelin/contracts-upgradeable@4.8.3': + resolution: {integrity: sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg==} + + '@openzeppelin/contracts-upgradeable@4.9.3': + resolution: {integrity: sha512-jjaHAVRMrE4UuZNfDwjlLGDxTHWIOwTJS2ldnc278a0gevfXfPr8hxKEVBGFBE96kl2G3VHDZhUimw/+G3TG2A==} + + '@openzeppelin/contracts@4.5.0': + resolution: {integrity: sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==} + + '@openzeppelin/contracts@4.7.3': + resolution: {integrity: sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==} + + '@openzeppelin/contracts@4.8.3': + resolution: {integrity: sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg==} + + '@openzeppelin/contracts@4.9.3': + resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} + + '@openzeppelin/upgrades-core@1.32.5': + resolution: {integrity: sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==} + hasBin: true + + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@2.2.2': + resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + engines: {node: '>=12'} + + '@prettier/sync@0.3.0': + resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} + peerDependencies: + prettier: ^3.0.0 + + '@scroll-tech/contracts@0.1.0': + resolution: {integrity: sha512-aBbDOc3WB/WveZdpJYcrfvMYMz7ZTEiW8M9XMJLba8p9FAR5KGYB/cV+8+EUsq3MKt7C1BfR+WnXoTVdvwIY6w==} + + '@scure/base@1.1.1': + resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} + + '@scure/bip32@1.1.0': + resolution: {integrity: sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q==} + + '@scure/bip39@1.1.0': + resolution: {integrity: sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==} + + '@sentry/core@5.30.0': + resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} + engines: {node: '>=6'} + + '@sentry/hub@5.30.0': + resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} + engines: {node: '>=6'} + + '@sentry/minimal@5.30.0': + resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} + engines: {node: '>=6'} + + '@sentry/node@5.30.0': + resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} + engines: {node: '>=6'} + + '@sentry/tracing@5.30.0': + resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} + engines: {node: '>=6'} + + '@sentry/types@5.30.0': + resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} + engines: {node: '>=6'} + + '@sentry/utils@5.30.0': + resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} + engines: {node: '>=6'} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@solidity-parser/parser@0.17.0': + resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} + + '@solidity-parser/parser@0.18.0': + resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} + + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + + '@truffle/abi-utils@0.3.2': + resolution: {integrity: sha512-32queMD64YKL/tmQgSV4Xs073dIaZ9tp7NP1icjwvFSA3Q9yeu7ApYbSbYMsx9H9zWkkVOsfcoJ2kJEieOCzsA==} + + '@truffle/contract-schema@3.4.10': + resolution: {integrity: sha512-BhRNRoRvlj2th6E5RNS0BnS0ZxQe01JJz8I7MjkGqdeXSvrn6qDCAnbmvhNgUv0l5h8w5+gBOQhAJhILf1shdQ==} + + '@tsconfig/node10@1.0.9': + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.3': + resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + + '@typechain/ethers-v5@7.2.0': + resolution: {integrity: sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==} + peerDependencies: + '@ethersproject/abi': ^5.0.0 + '@ethersproject/bytes': ^5.0.0 + '@ethersproject/providers': ^5.0.0 + ethers: ^5.1.3 + typechain: ^5.0.0 + typescript: '>=4.0.0' + + '@typechain/hardhat@7.0.0': + resolution: {integrity: sha512-XB79i5ewg9Met7gMVGfgVkmypicbnI25T5clJBEooMoW2161p4zvKFpoS2O+lBppQyMrPIZkdvl2M3LMDayVcA==} + peerDependencies: + '@ethersproject/abi': ^5.4.7 + '@ethersproject/providers': ^5.4.7 + '@typechain/ethers-v5': ^11.0.0 + ethers: ^5.4.7 + hardhat: ^2.9.9 + typechain: ^8.2.0 + + '@types/bn.js@4.11.6': + resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + + '@types/bn.js@5.1.1': + resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} + + '@types/cacheable-request@6.0.2': + resolution: {integrity: sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==} + + '@types/cbor@5.0.1': + resolution: {integrity: sha512-zVqJy2KzusZPLOgyGJDnOIbu3DxIGGqxYbEwtEEe4Z+la8jwIhOyb+GMrlHafs5tvKruwf8f8qOYP6zTvse/pw==} + + '@types/chai-as-promised@7.1.8': + resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} + + '@types/chai@4.3.16': + resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/deep-equal-in-any-order@1.0.3': + resolution: {integrity: sha512-jT0O3hAILDKeKbdWJ9FZLD0Xdfhz7hMvfyFlRWpirjiEVr8G+GZ4kVIzPIqM6x6Rpp93TNPgOAed4XmvcuV6Qg==} + + '@types/http-cache-semantics@4.0.1': + resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + + '@types/lru-cache@5.1.1': + resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/mocha@10.0.6': + resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} + + '@types/ms@0.7.31': + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + + '@types/node@12.19.16': + resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} + + '@types/node@20.12.12': + resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/pbkdf2@3.1.0': + resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} + + '@types/prettier@2.7.1': + resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} + + '@types/readable-stream@2.3.15': + resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} + + '@types/responselike@1.0.0': + resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} + + '@types/secp256k1@4.0.3': + resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} + + '@types/semver@7.5.0': + resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} + + '@typescript-eslint/eslint-plugin@7.10.0': + resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@7.10.0': + resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@7.10.0': + resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.10.0': + resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@7.10.0': + resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/typescript-estree@7.10.0': + resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.10.0': + resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/visitor-keys@7.10.0': + resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + abi-to-sol@0.6.6: + resolution: {integrity: sha512-PRn81rSpv6NXFPYQSw7ujruqIP6UkwZ/XoFldtiqCX8+2kHVc73xVaUVvdbro06vvBVZiwnxhEIGdI4BRMwGHw==} + hasBin: true + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + + acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + adm-zip@0.4.16: + resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} + engines: {node: '>=0.3.0'} + + aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.11.0: + resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@6.2.1: + resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} + engines: {node: '>=14.16'} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + antlr4@4.13.1-patch-1: + resolution: {integrity: sha512-OjFLWWLzDMV9rdFhpvroCWR4ooktNg9/nvVYSA5z28wuVpU36QUNuioR1XLnQtcjVlf8npjyz593PxnU/f/Cow==} + engines: {node: '>=16'} + + anymatch@3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-back@3.1.0: + resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} + engines: {node: '>=6'} + + array-back@4.0.2: + resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} + engines: {node: '>=8'} + + array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.0: + resolution: {integrity: sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==} + + base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + + bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + + better-ajv-errors@0.8.2: + resolution: {integrity: sha512-FnODTBJSQSHmJXDLPiC7ca0dC4S1HSTPv1+Hg2sm/C71i3Dj0l1jcUEaq/3OQ6MmnUveshTsUvUj65pDSr3Qow==} + peerDependencies: + ajv: 4.11.8 - 8 + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + bigint-crypto-utils@3.3.0: + resolution: {integrity: sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==} + engines: {node: '>=14.0.0'} + + bignumber.js@9.1.0: + resolution: {integrity: sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==} + + binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + + blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + + bn.js@4.11.6: + resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} + + bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + + bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + + boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + breakword@1.0.6: + resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + + bs58check@2.1.2: + resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + bufio@1.0.7: + resolution: {integrity: sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A==} + engines: {node: '>=8.0.0'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cacheable-lookup@6.1.0: + resolution: {integrity: sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.2: + resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} + engines: {node: '>=8'} + + call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@3.0.0: + resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} + + camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + cbor@5.2.0: + resolution: {integrity: sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==} + engines: {node: '>=6.0.0'} + + cbor@8.1.0: + resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} + engines: {node: '>=12.19'} + + cbor@9.0.2: + resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} + engines: {node: '>=16'} + + chai-as-promised@7.1.1: + resolution: {integrity: sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==} + peerDependencies: + chai: '>= 2.1.2 < 5' + + chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + change-case@3.0.2: + resolution: {integrity: sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + + chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + + ci-info@2.0.0: + resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-response@1.0.2: + resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + code-error-fragment@0.0.230: + resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==} + engines: {node: '>= 4'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + command-exists@1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + + command-line-args@5.2.1: + resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} + engines: {node: '>=4.0.0'} + + command-line-usage@6.1.3: + resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} + engines: {node: '>=8.0.0'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + commander@3.0.2: + resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} + + compare-versions@6.1.0: + resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + constant-case@2.0.0: + resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} + + cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + + core-js@3.30.1: + resolution: {integrity: sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==} + + cosmiconfig@8.2.0: + resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} + engines: {node: '>=14'} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + + cross-spawn@6.0.5: + resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + engines: {node: '>=4.8'} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + csv-generate@3.4.3: + resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} + + csv-parse@4.16.3: + resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} + + csv-stringify@5.6.5: + resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} + + csv@5.5.3: + resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} + engines: {node: '>= 0.1.90'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + + deep-equal-in-any-order@2.0.6: + resolution: {integrity: sha512-RfnWHQzph10YrUjvWwhd15Dne8ciSJcZ3U6OD7owPwiVwsdE5IFSoZGg8rlwJD11ES+9H5y8j3fCofviRHOqLQ==} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delete-empty@3.0.0: + resolution: {integrity: sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ==} + engines: {node: '>=10'} + hasBin: true + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diff@5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dot-case@2.1.1: + resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} + + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + + elliptic@6.5.4: + resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enquirer@2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-prettier@5.1.3: + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + ethereum-bloom-filters@1.0.10: + resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} + + ethereum-cryptography@0.1.3: + resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + + ethereum-cryptography@1.1.2: + resolution: {integrity: sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==} + + ethereumjs-abi@0.6.8: + resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + + ethereumjs-util@6.2.1: + resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + + ethereumjs-util@7.1.5: + resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} + engines: {node: '>=10.0.0'} + + ethers@5.7.2: + resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} + + ethjs-unit@0.1.6: + resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} + engines: {node: '>=6.5.0', npm: '>=3'} + + ethjs-util@0.1.6: + resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} + engines: {node: '>=6.5.0', npm: '>=3'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + fast-check@3.1.1: + resolution: {integrity: sha512-3vtXinVyuUKCKFKYcwXhGE6NtGWkqF8Yh3rvMZNzmwz8EPrgoc/v4pDdLHyLnCyCI5MZpZZkDEwFyXyEONOxpA==} + engines: {node: '>=8.0.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.2.0: + resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} + + fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.6.0: + resolution: {integrity: sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + find-replace@3.0.0: + resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} + engines: {node: '>=4.0.0'} + + find-up@2.1.0: + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + + find-yarn-workspace-root@2.0.0: + resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + form-data-encoder@1.7.1: + resolution: {integrity: sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==} + + fp-ts@1.19.3: + resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} + + fs-extra@0.30.0: + resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-stream@5.1.0: + resolution: {integrity: sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + + glob@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + got@12.1.0: + resolution: {integrity: sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==} + engines: {node: '>=14.16'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + hardhat-abi-exporter@2.10.1: + resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} + engines: {node: '>=14.14.0'} + peerDependencies: + hardhat: ^2.0.0 + + hardhat-ignore-warnings@0.2.11: + resolution: {integrity: sha512-+nHnRbP6COFZaXE7HAY7TZNE3au5vHe5dkcnyq0XaP07ikT2fJ3NhFY0vn7Deh4Qbz0Z/9Xpnj2ki6Ktgk61pg==} + + hardhat@2.20.1: + resolution: {integrity: sha512-q75xDQiQtCZcTMBwjTovrXEU5ECr49baxr4/OBkIu/ULTPzlB20yk1dRWNmD2IFbAeAeXggaWvQAdpiScaHtPw==} + hasBin: true + peerDependencies: + ts-node: '*' + typescript: '*' + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + header-case@1.0.1: + resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + http-cache-semantics@4.0.3: + resolution: {integrity: sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http2-wrapper@2.1.11: + resolution: {integrity: sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-id@1.0.2: + resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + immutable@4.1.0: + resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + io-ts@1.10.4: + resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} + + is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-ci@2.0.0: + resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} + hasBin: true + + is-core-module@2.10.0: + resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.2: + resolution: {integrity: sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hex-prefixed@1.0.0: + resolution: {integrity: sha1-fY035q135dEnFIkTxXPggtd39VQ=} + engines: {node: '>=6.5.0', npm: '>=3'} + + is-lower-case@1.1.3: + resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} + + is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-symbol@1.0.3: + resolution: {integrity: sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-upper-case@1.1.2: + resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-sdsl@4.4.2: + resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==} + + js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-to-ast@2.1.0: + resolution: {integrity: sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==} + engines: {node: '>= 4'} + + jsonfile@2.4.0: + resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + keccak@3.0.2: + resolution: {integrity: sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==} + engines: {node: '>=10.0.0'} + + keyv@4.5.0: + resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + klaw-sync@6.0.0: + resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} + + klaw@1.3.1: + resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + latest-version@7.0.0: + resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} + engines: {node: '>=14.16'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.2.2: + resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.0.1: + resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} + engines: {node: '>=18.0.0'} + + load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + + locate-path@2.0.0: + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + + lodash.mapvalues@4.6.0: + resolution: {integrity: sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lower-case-first@1.0.2: + resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==} + + lower-case@1.1.4: + resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + + lru_map@0.3.3: + resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + memorystream@0.3.1: + resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} + engines: {node: '>= 0.10.0'} + + meow@6.1.1: + resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} + engines: {node: '>=8'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.0.1: + resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} + engines: {node: '>=10'} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mixme@0.5.10: + resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} + engines: {node: '>= 8.0.0'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mnemonist@0.38.5: + resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} + + mocha@10.2.0: + resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} + engines: {node: '>= 14.0.0'} + hasBin: true + + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.3: + resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + neodoc@2.0.2: + resolution: {integrity: sha512-NAppJ0YecKWdhSXFYCHbo6RutiX8vOt/Jo3l46mUg6pQlpJNaqc5cGxdrW2jITQm5JIYySbFVPDl3RrREXNyPw==} + + nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + + no-case@2.3.2: + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} + + node-addon-api@2.0.2: + resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + + node-fetch@2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build@4.5.0: + resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==} + hasBin: true + + node-interval-tree@2.1.2: + resolution: {integrity: sha512-bJ9zMDuNGzVQg1xv0bCPzyEDxHgbrx7/xGj6CDokvizZZmastPsOh0JJLuY8wA5q2SfX1TLNMk7XNV8WxbGxzA==} + engines: {node: '>= 14.0.0'} + + nofilter@1.0.4: + resolution: {integrity: sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==} + engines: {node: '>=8'} + + nofilter@3.1.0: + resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} + engines: {node: '>=12.19'} + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + number-to-bn@1.7.0: + resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} + engines: {node: '>=6.5.0', npm: '>=3'} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + obliterator@2.0.4: + resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + open@7.4.2: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + + optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + + ordinal@1.0.3: + resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@1.3.0: + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@2.0.0: + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-try@1.0.0: + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} + + param-case@2.1.1: + resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + pascal-case@2.0.1: + resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} + + patch-package@6.5.1: + resolution: {integrity: sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==} + engines: {node: '>=10', npm: '>5'} + hasBin: true + + path-case@2.1.1: + resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} + + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-starts-with@2.0.1: + resolution: {integrity: sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + preferred-pm@3.1.3: + resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} + engines: {node: '>=10'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-solidity@1.3.1: + resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} + engines: {node: '>=16'} + peerDependencies: + prettier: '>=2.3.0' + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + + pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + + punycode@2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + + pure-rand@5.0.3: + resolution: {integrity: sha512-9N8x1h8dptBQpHyC7aZMS+iNOAm97WMGY0AFrguU1cpfW3I5jINkWe5BIY5md0ofy+1TCIELsVcm/GJXZSaPbw==} + + quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + readable-stream@3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + reduce-flatten@2.0.0: + resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} + engines: {node: '>=6'} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + + registry-auth-token@5.0.2: + resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} + engines: {node: '>=14'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve@1.17.0: + resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + + resolve@1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.3.1: + resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} + + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + + rlp@2.2.7: + resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} + hasBin: true + + run-parallel@1.1.9: + resolution: {integrity: sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==} + + rust-verkle-wasm@0.0.1: + resolution: {integrity: sha512-BN6fiTsxcd2dCECz/cHtGTt9cdLJR925nh7iAuRcj8ymKw7OOaPmCneQZ7JePOJ/ia27TjEL91VdOi88Yf+mcA==} + + rustbn-wasm@0.2.0: + resolution: {integrity: sha512-FThvYFNTqrEKGqXuseeg0zR7yROh/6U1617mCHF68OVqrN1tNKRN7Tdwy4WayPVsCmmK+eMxtIZX1qL6JxTkMg==} + + safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + + secp256k1@4.0.3: + resolution: {integrity: sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==} + engines: {node: '>=10.0.0'} + + semver@5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + + semver@6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + sentence-case@2.1.1: + resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} + + serialize-javascript@6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + + shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@2.0.0: + resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} + engines: {node: '>=6'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + smartwrap@2.0.2: + resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} + engines: {node: '>=6'} + hasBin: true + + snake-case@2.1.0: + resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} + + solc@0.7.3: + resolution: {integrity: sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==} + engines: {node: '>=8.0.0'} + hasBin: true + + solhint-plugin-prettier@0.1.0: + resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-solidity: ^1.0.0 + + solhint@5.0.1: + resolution: {integrity: sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg==} + hasBin: true + + solidity-ast@0.4.56: + resolution: {integrity: sha512-HgmsA/Gfklm/M8GFbCX/J1qkVH0spXHgALCNZ8fA8x5X+MFdn/8CP2gr5OVyXjXw6RZTPC/Sxl2RUDQOXyNMeA==} + + solidity-comments-darwin-arm64@0.0.2: + resolution: {integrity: sha512-HidWkVLSh7v+Vu0CA7oI21GWP/ZY7ro8g8OmIxE8oTqyMwgMbE8F1yc58Sj682Hj199HCZsjmtn1BE4PCbLiGA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + solidity-comments-darwin-x64@0.0.2: + resolution: {integrity: sha512-Zjs0Ruz6faBTPT6fBecUt6qh4CdloT8Bwoc0+qxRoTn9UhYscmbPQkUgQEbS0FQPysYqVzzxJB4h1Ofbf4wwtA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + solidity-comments-extractor@0.0.8: + resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} + + solidity-comments-freebsd-x64@0.0.2: + resolution: {integrity: sha512-8Qe4mpjuAxFSwZJVk7B8gAoLCdbtS412bQzBwk63L8dmlHogvE39iT70aAk3RHUddAppT5RMBunlPUCFYJ3ZTw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + solidity-comments-linux-arm64-gnu@0.0.2: + resolution: {integrity: sha512-spkb0MZZnmrP+Wtq4UxP+nyPAVRe82idOjqndolcNR0S9Xvu4ebwq+LvF4HiUgjTDmeiqYiFZQ8T9KGdLSIoIg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + solidity-comments-linux-arm64-musl@0.0.2: + resolution: {integrity: sha512-guCDbHArcjE+JDXYkxx5RZzY1YF6OnAKCo+sTC5fstyW/KGKaQJNPyBNWuwYsQiaEHpvhW1ha537IvlGek8GqA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + solidity-comments-linux-x64-gnu@0.0.2: + resolution: {integrity: sha512-zIqLehBK/g7tvrFmQljrfZXfkEeLt2v6wbe+uFu6kH/qAHZa7ybt8Vc0wYcmjo2U0PeBm15d79ee3AkwbIjFdQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + solidity-comments-linux-x64-musl@0.0.2: + resolution: {integrity: sha512-R9FeDloVlFGTaVkOlELDVC7+1Tjx5WBPI5L8r0AGOPHK3+jOcRh6sKYpI+VskSPDc3vOO46INkpDgUXrKydlIw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + solidity-comments-win32-arm64-msvc@0.0.2: + resolution: {integrity: sha512-QnWJoCQcJj+rnutULOihN9bixOtYWDdF5Rfz9fpHejL1BtNjdLW1om55XNVHGAHPqBxV4aeQQ6OirKnp9zKsug==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + solidity-comments-win32-ia32-msvc@0.0.2: + resolution: {integrity: sha512-vUg4nADtm/NcOtlIymG23NWJUSuMsvX15nU7ynhGBsdKtt8xhdP3C/zA6vjDk8Jg+FXGQL6IHVQ++g/7rSQi0w==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + solidity-comments-win32-x64-msvc@0.0.2: + resolution: {integrity: sha512-36j+KUF4V/y0t3qatHm/LF5sCUCBx2UndxE1kq5bOzh/s+nQgatuyB+Pd5BfuPQHdWu2KaExYe20FlAa6NL7+Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + solidity-comments@0.0.2: + resolution: {integrity: sha512-G+aK6qtyUfkn1guS8uzqUeua1dURwPlcOjoTYW/TwmXAcE7z/1+oGCfZUdMSe4ZMKklNbVZNiG5ibnF8gkkFfw==} + engines: {node: '>= 12'} + + sort-any@2.0.0: + resolution: {integrity: sha512-T9JoiDewQEmWcnmPn/s9h/PH9t3d/LSWi0RgVmXSuDYeZXTZOZ1/wrK2PHaptuR1VXe3clLLt0pD6sgVOwjNEA==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spawndamnit@2.0.0: + resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + + spdx-correct@3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + + spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.12: + resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stacktrace-parser@0.1.10: + resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} + engines: {node: '>=6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + stream-transform@2.1.3: + resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-format@2.0.0: + resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} + engines: {node: '>=18'} + + string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-hex-prefix@1.0.0: + resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=} + engines: {node: '>=6.5.0', npm: '>=3'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + swap-case@1.1.2: + resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} + + synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + + table-layout@1.0.2: + resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} + engines: {node: '>=8.0.0'} + + table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + title-case@2.1.1: + resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-command-line-args@2.5.1: + resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} + hasBin: true + + ts-essentials@7.0.3: + resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} + peerDependencies: + typescript: '>=3.7.0' + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + tsort@0.0.1: + resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} + + tty-table@4.2.3: + resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} + engines: {node: '>=8.0.0'} + hasBin: true + + tweetnacl-util@0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + typechain@8.3.2: + resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} + hasBin: true + peerDependencies: + typescript: '>=4.3.0' + + typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + + typical@4.0.0: + resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} + engines: {node: '>=8'} + + typical@5.2.0: + resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} + engines: {node: '>=8'} + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + upper-case-first@1.1.2: + resolution: {integrity: sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==} + + upper-case@1.1.3: + resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + web3-utils@1.7.4: + resolution: {integrity: sha512-acBdm6Evd0TEZRnChM/MCvGsMwYKmSh7OaUfNf5OKG0CIeGWD/6gqLOWIwmwSnre/2WrA1nKGId5uW2e5EfluA==} + engines: {node: '>=8.0.0'} -packages: + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: true + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - /@arbitrum/nitro-contracts@1.1.1: - resolution: {integrity: sha512-4Tyk3XVHz+bm8UujUC78LYSw3xAxyYvBCxfEX4z3qE4/ww7Qck/rmce5gbHMzQjArEAzAP2YSfYIFuIFuRXtfg==} - requiresBuild: true + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-module@2.0.0: + resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} + + which-pm@2.0.0: + resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + engines: {node: '>=8.15'} + + which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + + wordwrapjs@4.0.1: + resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} + engines: {node: '>=8.0.0'} + + workerpool@6.2.1: + resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@7.5.9: + resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@20.2.4: + resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@aashutoshrathi/word-wrap@1.2.6': {} + + '@arbitrum/nitro-contracts@1.1.1': dependencies: '@offchainlabs/upgrade-executor': 1.1.0-beta.0 '@openzeppelin/contracts': 4.5.0 '@openzeppelin/contracts-upgradeable': 4.5.2 patch-package: 6.5.1 - dev: false - /@arbitrum/token-bridge-contracts@1.1.2: - resolution: {integrity: sha512-k7AZXiB2HFecJ1KfaDBqgOKe3Loo1ttGLC7hUOVB+0YrihIR6cYpJRuqKSKK4YCy+FF21AUDtaG3x57OFM667Q==} + '@arbitrum/token-bridge-contracts@1.1.2': dependencies: '@arbitrum/nitro-contracts': 1.1.1 '@offchainlabs/upgrade-executor': 1.1.0-beta.0 @@ -192,34 +3601,26 @@ packages: '@openzeppelin/upgrades-core': 1.32.5 transitivePeerDependencies: - supports-color - dev: false - /@babel/code-frame@7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} + '@babel/code-frame@7.18.6': dependencies: '@babel/highlight': 7.18.6 - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.19.1': {} - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} + '@babel/highlight@7.18.6': dependencies: '@babel/helper-validator-identifier': 7.19.1 chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/runtime@7.24.0: - resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} - engines: {node: '>=6.9.0'} + '@babel/runtime@7.24.0': dependencies: regenerator-runtime: 0.14.1 - /@changesets/apply-release-plan@7.0.1: - resolution: {integrity: sha512-aPdSq/R++HOyfEeBGjEe6LNG8gs0KMSyRETD/J2092OkNq8mOioAxyKjMbvVUdzgr/HTawzMOz7lfw339KnsCA==} + '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c': {} + + '@changesets/apply-release-plan@7.0.1': dependencies: '@babel/runtime': 7.24.0 '@changesets/config': 3.0.0 @@ -234,10 +3635,8 @@ packages: prettier: 2.8.8 resolve-from: 5.0.0 semver: 7.6.2 - dev: false - /@changesets/assemble-release-plan@6.0.0: - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + '@changesets/assemble-release-plan@6.0.0': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 @@ -245,27 +3644,20 @@ packages: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 semver: 7.6.2 - dev: false - /@changesets/changelog-git@0.2.0: - resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} + '@changesets/changelog-git@0.2.0': dependencies: '@changesets/types': 6.0.0 - dev: false - /@changesets/changelog-github@0.5.0: - resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} + '@changesets/changelog-github@0.5.0': dependencies: '@changesets/get-github-info': 0.6.0 '@changesets/types': 6.0.0 dotenv: 8.6.0 transitivePeerDependencies: - encoding - dev: false - /@changesets/cli@2.27.3: - resolution: {integrity: sha512-ve/VpWApILlSs8cr0okNx5C2LKRawI9XZgvfmf58S8sar2nhx5DPJREFXYZBahs0FeTfvH0rdVl+nGe8QF45Ig==} - hasBin: true + '@changesets/cli@2.27.3': dependencies: '@babel/runtime': 7.24.0 '@changesets/apply-release-plan': 7.0.1 @@ -299,10 +3691,8 @@ packages: spawndamnit: 2.0.0 term-size: 2.2.1 tty-table: 4.2.3 - dev: false - /@changesets/config@3.0.0: - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + '@changesets/config@3.0.0': dependencies: '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.0.0 @@ -311,35 +3701,27 @@ packages: '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 micromatch: 4.0.5 - dev: false - /@changesets/errors@0.2.0: - resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + '@changesets/errors@0.2.0': dependencies: extendable-error: 0.1.7 - dev: false - /@changesets/get-dependents-graph@2.0.0: - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + '@changesets/get-dependents-graph@2.0.0': dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 semver: 7.6.2 - dev: false - /@changesets/get-github-info@0.6.0: - resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} + '@changesets/get-github-info@0.6.0': dependencies: dataloader: 1.4.0 node-fetch: 2.6.7 transitivePeerDependencies: - encoding - dev: false - /@changesets/get-release-plan@4.0.0: - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + '@changesets/get-release-plan@4.0.0': dependencies: '@babel/runtime': 7.24.0 '@changesets/assemble-release-plan': 6.0.0 @@ -348,14 +3730,10 @@ packages: '@changesets/read': 0.6.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - dev: false - /@changesets/get-version-range-type@0.4.0: - resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - dev: false + '@changesets/get-version-range-type@0.4.0': {} - /@changesets/git@3.0.0: - resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + '@changesets/git@3.0.0': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 @@ -364,33 +3742,25 @@ packages: is-subdir: 1.2.0 micromatch: 4.0.5 spawndamnit: 2.0.0 - dev: false - /@changesets/logger@0.1.0: - resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + '@changesets/logger@0.1.0': dependencies: chalk: 2.4.2 - dev: false - /@changesets/parse@0.4.0: - resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} + '@changesets/parse@0.4.0': dependencies: '@changesets/types': 6.0.0 js-yaml: 3.14.1 - dev: false - /@changesets/pre@2.0.0: - resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + '@changesets/pre@2.0.0': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - dev: false - /@changesets/read@0.6.0: - resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + '@changesets/read@0.6.0': dependencies: '@babel/runtime': 7.24.0 '@changesets/git': 3.0.0 @@ -400,54 +3770,34 @@ packages: chalk: 2.4.2 fs-extra: 7.0.1 p-filter: 2.1.0 - dev: false - /@changesets/types@4.1.0: - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - dev: false + '@changesets/types@4.1.0': {} - /@changesets/types@6.0.0: - resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - dev: false + '@changesets/types@6.0.0': {} - /@changesets/write@0.3.1: - resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} + '@changesets/write@0.3.1': dependencies: '@babel/runtime': 7.24.0 '@changesets/types': 6.0.0 fs-extra: 7.0.1 human-id: 1.0.2 prettier: 2.8.8 - dev: false - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 - dev: true - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true + '@eslint-community/regexpp@4.10.0': {} - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -457,17 +3807,10 @@ packages: strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - dev: true - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + '@eslint/js@8.57.0': {} - /@eth-optimism/contracts@0.6.0(ethers@5.7.2): - resolution: {integrity: sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w==} - peerDependencies: - ethers: ^5 + '@eth-optimism/contracts@0.6.0(ethers@5.7.2)': dependencies: '@eth-optimism/core-utils': 0.12.0 '@ethersproject/abstract-provider': 5.7.0 @@ -476,10 +3819,8 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate - dev: false - /@eth-optimism/core-utils@0.12.0: - resolution: {integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==} + '@eth-optimism/core-utils@0.12.0': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -500,21 +3841,16 @@ packages: transitivePeerDependencies: - bufferutil - utf-8-validate - dev: false - /@ethereum-waffle/mock-contract@3.4.4: - resolution: {integrity: sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA==} - engines: {node: '>=10.0'} + '@ethereum-waffle/mock-contract@3.4.4': dependencies: '@ethersproject/abi': 5.7.0 ethers: 5.7.2 transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true - /@ethersproject/abi@5.7.0: - resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} + '@ethersproject/abi@5.7.0': dependencies: '@ethersproject/address': 5.7.0 '@ethersproject/bignumber': 5.7.0 @@ -526,8 +3862,7 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - /@ethersproject/abstract-provider@5.7.0: - resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + '@ethersproject/abstract-provider@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -537,8 +3872,7 @@ packages: '@ethersproject/transactions': 5.7.0 '@ethersproject/web': 5.7.1 - /@ethersproject/abstract-signer@5.7.0: - resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} + '@ethersproject/abstract-signer@5.7.0': dependencies: '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/bignumber': 5.7.0 @@ -546,8 +3880,7 @@ packages: '@ethersproject/logger': 5.0.6 '@ethersproject/properties': 5.7.0 - /@ethersproject/address@5.7.0: - resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} + '@ethersproject/address@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -555,36 +3888,30 @@ packages: '@ethersproject/logger': 5.0.6 '@ethersproject/rlp': 5.7.0 - /@ethersproject/base64@5.7.0: - resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + '@ethersproject/base64@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 - /@ethersproject/basex@5.7.0: - resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} + '@ethersproject/basex@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/properties': 5.7.0 - /@ethersproject/bignumber@5.7.0: - resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + '@ethersproject/bignumber@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.0.6 bn.js: 5.2.1 - /@ethersproject/bytes@5.7.0: - resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + '@ethersproject/bytes@5.7.0': dependencies: '@ethersproject/logger': 5.0.6 - /@ethersproject/constants@5.7.0: - resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + '@ethersproject/constants@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 - /@ethersproject/contracts@5.7.0: - resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} + '@ethersproject/contracts@5.7.0': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -597,8 +3924,7 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/transactions': 5.7.0 - /@ethersproject/hash@5.7.0: - resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} + '@ethersproject/hash@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/address': 5.7.0 @@ -610,8 +3936,7 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - /@ethersproject/hdnode@5.7.0: - resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} + '@ethersproject/hdnode@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/basex': 5.7.0 @@ -626,8 +3951,7 @@ packages: '@ethersproject/transactions': 5.7.0 '@ethersproject/wordlists': 5.7.0 - /@ethersproject/json-wallets@5.7.0: - resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} + '@ethersproject/json-wallets@5.7.0': dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/address': 5.7.0 @@ -643,33 +3967,27 @@ packages: aes-js: 3.0.0 scrypt-js: 3.0.1 - /@ethersproject/keccak256@5.7.0: - resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + '@ethersproject/keccak256@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 js-sha3: 0.8.0 - /@ethersproject/logger@5.0.6: - resolution: {integrity: sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ==} + '@ethersproject/logger@5.0.6': {} - /@ethersproject/networks@5.7.1: - resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + '@ethersproject/networks@5.7.1': dependencies: '@ethersproject/logger': 5.0.6 - /@ethersproject/pbkdf2@5.7.0: - resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} + '@ethersproject/pbkdf2@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/sha2': 5.7.0 - /@ethersproject/properties@5.7.0: - resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + '@ethersproject/properties@5.7.0': dependencies: '@ethersproject/logger': 5.0.6 - /@ethersproject/providers@5.7.2: - resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} + '@ethersproject/providers@5.7.2': dependencies: '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 @@ -695,27 +4013,23 @@ packages: - bufferutil - utf-8-validate - /@ethersproject/random@5.7.0: - resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} + '@ethersproject/random@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.0.6 - /@ethersproject/rlp@5.7.0: - resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + '@ethersproject/rlp@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.0.6 - /@ethersproject/sha2@5.7.0: - resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} + '@ethersproject/sha2@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.0.6 hash.js: 1.1.7 - /@ethersproject/signing-key@5.7.0: - resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} + '@ethersproject/signing-key@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/logger': 5.0.6 @@ -724,8 +4038,7 @@ packages: elliptic: 6.5.4 hash.js: 1.1.7 - /@ethersproject/solidity@5.7.0: - resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==} + '@ethersproject/solidity@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -734,15 +4047,13 @@ packages: '@ethersproject/sha2': 5.7.0 '@ethersproject/strings': 5.7.0 - /@ethersproject/strings@5.7.0: - resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + '@ethersproject/strings@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/constants': 5.7.0 '@ethersproject/logger': 5.0.6 - /@ethersproject/transactions@5.7.0: - resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} + '@ethersproject/transactions@5.7.0': dependencies: '@ethersproject/address': 5.7.0 '@ethersproject/bignumber': 5.7.0 @@ -754,15 +4065,13 @@ packages: '@ethersproject/rlp': 5.7.0 '@ethersproject/signing-key': 5.7.0 - /@ethersproject/units@5.7.0: - resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} + '@ethersproject/units@5.7.0': dependencies: '@ethersproject/bignumber': 5.7.0 '@ethersproject/constants': 5.7.0 '@ethersproject/logger': 5.0.6 - /@ethersproject/wallet@5.7.0: - resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} + '@ethersproject/wallet@5.7.0': dependencies: '@ethersproject/abstract-provider': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 @@ -780,8 +4089,7 @@ packages: '@ethersproject/transactions': 5.7.0 '@ethersproject/wordlists': 5.7.0 - /@ethersproject/web@5.7.1: - resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} + '@ethersproject/web@5.7.1': dependencies: '@ethersproject/base64': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -789,8 +4097,7 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - /@ethersproject/wordlists@5.7.0: - resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} + '@ethersproject/wordlists@5.7.0': dependencies: '@ethersproject/bytes': 5.7.0 '@ethersproject/hash': 5.7.0 @@ -798,58 +4105,37 @@ packages: '@ethersproject/properties': 5.7.0 '@ethersproject/strings': 5.7.0 - /@fastify/busboy@2.1.1: - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - dev: true + '@fastify/busboy@2.1.1': {} - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color - dev: true - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true + '@humanwhocodes/module-importer@1.0.1': {} - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: true + '@humanwhocodes/object-schema@2.0.3': {} - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/resolve-uri@3.1.1': {} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true + '@jridgewell/sourcemap-codec@1.4.15': {} - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@manypkg/find-root@1.1.0: - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.24.0 '@types/node': 12.19.16 find-up: 4.1.0 fs-extra: 8.1.0 - dev: false - /@manypkg/get-packages@1.1.3: - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@manypkg/get-packages@1.1.3': dependencies: '@babel/runtime': 7.24.0 '@changesets/types': 4.1.0 @@ -857,48 +4143,32 @@ packages: fs-extra: 8.1.0 globby: 11.1.0 read-yaml-file: 1.1.0 - dev: false - /@metamask/eth-sig-util@4.0.1: - resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} - engines: {node: '>=12.0.0'} + '@metamask/eth-sig-util@4.0.1': dependencies: ethereumjs-abi: 0.6.8 ethereumjs-util: 6.2.1 ethjs-util: 0.1.6 tweetnacl: 1.0.3 tweetnacl-util: 0.15.1 - dev: true - /@noble/hashes@1.1.2: - resolution: {integrity: sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==} - dev: true + '@noble/hashes@1.1.2': {} - /@noble/secp256k1@1.6.3: - resolution: {integrity: sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==} - dev: true + '@noble/secp256k1@1.6.3': {} - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.1.9 - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.6.0 - /@nomicfoundation/ethereumjs-block@5.0.4: - resolution: {integrity: sha512-AcyacJ9eX/uPEvqsPiB+WO1ymE+kyH48qGGiGV+YTojdtas8itUTW5dehDSOXEEItWGbbzEJ4PRqnQZlWaPvDw==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-block@5.0.4': dependencies: '@nomicfoundation/ethereumjs-common': 4.0.4 '@nomicfoundation/ethereumjs-rlp': 5.0.4 @@ -908,11 +4178,8 @@ packages: ethereum-cryptography: 0.1.3 transitivePeerDependencies: - c-kzg - dev: true - /@nomicfoundation/ethereumjs-blockchain@7.0.4: - resolution: {integrity: sha512-jYsd/kwzbmpnxx86tXsYV8wZ5xGvFL+7/P0c6OlzpClHsbFzeF41KrYA9scON8Rg6bZu3ZTv6JOAgj3t7USUfg==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-blockchain@7.0.4': dependencies: '@nomicfoundation/ethereumjs-block': 5.0.4 '@nomicfoundation/ethereumjs-common': 4.0.4 @@ -921,25 +4188,20 @@ packages: '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 lru-cache: 10.2.2 transitivePeerDependencies: - c-kzg - supports-color - dev: true - /@nomicfoundation/ethereumjs-common@4.0.4: - resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} + '@nomicfoundation/ethereumjs-common@4.0.4': dependencies: '@nomicfoundation/ethereumjs-util': 9.0.4 transitivePeerDependencies: - c-kzg - dev: true - /@nomicfoundation/ethereumjs-ethash@3.0.4: - resolution: {integrity: sha512-xvIrwIMl9sSaiYKRem68+O7vYdj7Q2XWv5P7JXiIkn83918QzWHvqbswTRsH7+r6X1UEvdsURRnZbvZszEjAaQ==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-ethash@3.0.4': dependencies: '@nomicfoundation/ethereumjs-block': 5.0.4 '@nomicfoundation/ethereumjs-rlp': 5.0.4 @@ -948,57 +4210,41 @@ packages: ethereum-cryptography: 0.1.3 transitivePeerDependencies: - c-kzg - dev: true - /@nomicfoundation/ethereumjs-evm@2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2): - resolution: {integrity: sha512-lTyZZi1KpeMHzaO6cSVisR2tjiTTedjo7PcmhI/+GNFo9BmyY6QYzGeSti0sFttmjbEMioHgXxl5yrLNRg6+1w==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-evm@2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2)': dependencies: '@nomicfoundation/ethereumjs-common': 4.0.4 '@nomicfoundation/ethereumjs-statemanager': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 '@types/debug': 4.1.12 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 rustbn-wasm: 0.2.0 transitivePeerDependencies: - '@nomicfoundation/ethereumjs-verkle' - c-kzg - supports-color - dev: true - /@nomicfoundation/ethereumjs-rlp@5.0.4: - resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} - engines: {node: '>=18'} - hasBin: true - dev: true + '@nomicfoundation/ethereumjs-rlp@5.0.4': {} - /@nomicfoundation/ethereumjs-statemanager@2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2): - resolution: {integrity: sha512-HPDjeFrxw6llEi+BzqXkZ+KkvFnTOPczuHBtk21hRlDiuKuZz32dPzlhpRsDBGV1b5JTmRDUVqCS1lp3Gghw4Q==} - peerDependencies: - '@nomicfoundation/ethereumjs-verkle': 0.0.2 - peerDependenciesMeta: - '@nomicfoundation/ethereumjs-verkle': - optional: true + '@nomicfoundation/ethereumjs-statemanager@2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2)': dependencies: '@nomicfoundation/ethereumjs-common': 4.0.4 '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - '@nomicfoundation/ethereumjs-verkle': 0.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 js-sdsl: 4.4.2 lru-cache: 10.2.2 + optionalDependencies: + '@nomicfoundation/ethereumjs-verkle': 0.0.2 transitivePeerDependencies: - c-kzg - supports-color - dev: true - /@nomicfoundation/ethereumjs-trie@6.0.4: - resolution: {integrity: sha512-3nSwQiFMvr2VFe/aZUyinuohYvtytUqZCUCvIWcPJ/BwJH6oQdZRB42aNFBJ/8nAh2s3OcroWpBLskzW01mFKA==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-trie@6.0.4': dependencies: '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 @@ -1008,39 +4254,20 @@ packages: readable-stream: 3.6.0 transitivePeerDependencies: - c-kzg - dev: true - /@nomicfoundation/ethereumjs-tx@5.0.4: - resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true + '@nomicfoundation/ethereumjs-tx@5.0.4': dependencies: '@nomicfoundation/ethereumjs-common': 4.0.4 '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 ethereum-cryptography: 0.1.3 - dev: true - /@nomicfoundation/ethereumjs-util@9.0.4: - resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true + '@nomicfoundation/ethereumjs-util@9.0.4': dependencies: '@nomicfoundation/ethereumjs-rlp': 5.0.4 ethereum-cryptography: 0.1.3 - dev: true - /@nomicfoundation/ethereumjs-verkle@0.0.2: - resolution: {integrity: sha512-bjnfZElpYGK/XuuVRmLS3yDvr+cDs85D9oonZ0YUa5A3lgFgokWMp76zXrxX2jVQ0BfHaw12y860n1+iOi6yFQ==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-verkle@0.0.2': dependencies: '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 @@ -1048,11 +4275,8 @@ packages: rust-verkle-wasm: 0.0.1 transitivePeerDependencies: - c-kzg - dev: true - /@nomicfoundation/ethereumjs-vm@7.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2): - resolution: {integrity: sha512-gsA4IhmtWHI4BofKy3kio9W+dqZQs5Ji5mLjLYxHCkat+JQBUt5szjRKra2F9nGDJ2XcI/wWb0YWUFNgln4zRQ==} - engines: {node: '>=18'} + '@nomicfoundation/ethereumjs-vm@7.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2)': dependencies: '@nomicfoundation/ethereumjs-block': 5.0.4 '@nomicfoundation/ethereumjs-blockchain': 7.0.4 @@ -1063,168 +4287,85 @@ packages: '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 transitivePeerDependencies: - '@nomicfoundation/ethereumjs-verkle' - c-kzg - supports-color - dev: true - /@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3)(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1): - resolution: {integrity: sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==} - peerDependencies: - '@nomiclabs/hardhat-ethers': ^2.0.0 - chai: ^4.2.0 - ethers: ^5.0.0 - hardhat: ^2.9.4 + '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)))(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': dependencies: '@ethersproject/abi': 5.7.0 - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) '@types/chai-as-promised': 7.1.8 chai: 4.4.1 chai-as-promised: 7.1.1(chai@4.4.1) deep-eql: 4.1.3 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) ordinal: 1.0.3 - dev: true - /@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1): - resolution: {integrity: sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA==} - peerDependencies: - ethers: ^6.1.0 - hardhat: ^2.0.0 + '@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - dev: true - /@nomicfoundation/hardhat-network-helpers@1.0.10(hardhat@2.20.1): - resolution: {integrity: sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==} - peerDependencies: - hardhat: ^2.9.5 + '@nomicfoundation/hardhat-network-helpers@1.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) - dev: true + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) - /@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.20.1): - resolution: {integrity: sha512-jiYHBX+K6bBN0YhwFHQ5SWWc3dQZliM3pdgpH33C7tnsVACsX1ubZn6gZ9hfwlzG0tyjFM72XQhpaXQ56cE6Ew==} - peerDependencies: - hardhat: ^2.0.4 + '@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 cbor: 8.1.0 chalk: 2.4.2 - debug: 4.3.4 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) + debug: 4.3.4(supports-color@8.1.1) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) lodash.clonedeep: 4.5.0 semver: 6.3.0 table: 6.8.1 undici: 5.28.4 transitivePeerDependencies: - supports-color - dev: true - /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0: - resolution: {integrity: sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0: - resolution: {integrity: sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0: - resolution: {integrity: sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0: - resolution: {integrity: sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0: - resolution: {integrity: sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0: - resolution: {integrity: sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0: - resolution: {integrity: sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0: - resolution: {integrity: sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0: - resolution: {integrity: sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0: - resolution: {integrity: sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true + '@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0': optional: true - /@nomicfoundation/solidity-analyzer@0.1.0: - resolution: {integrity: sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg==} - engines: {node: '>= 12'} + '@nomicfoundation/solidity-analyzer@0.1.0': optionalDependencies: '@nomicfoundation/solidity-analyzer-darwin-arm64': 0.1.0 '@nomicfoundation/solidity-analyzer-darwin-x64': 0.1.0 @@ -1236,164 +4377,101 @@ packages: '@nomicfoundation/solidity-analyzer-win32-arm64-msvc': 0.1.0 '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.0 '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0 - dev: true - /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1): - resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} - peerDependencies: - ethers: ^5.0.0 - hardhat: ^2.0.0 + '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': dependencies: ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) - dev: true + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) - /@offchainlabs/upgrade-executor@1.1.0-beta.0: - resolution: {integrity: sha512-mpn6PHjH/KDDjNX0pXHEKdyv8m6DVGQiI2nGzQn0JbM1nOSHJpWx6fvfjtH7YxHJ6zBZTcsKkqGkFKDtCfoSLw==} + '@offchainlabs/upgrade-executor@1.1.0-beta.0': dependencies: '@openzeppelin/contracts': 4.7.3 '@openzeppelin/contracts-upgradeable': 4.7.3 - dev: false - /@openzeppelin/contracts-upgradeable@4.5.2: - resolution: {integrity: sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA==} - dev: false + '@openzeppelin/contracts-upgradeable@4.5.2': {} - /@openzeppelin/contracts-upgradeable@4.7.3: - resolution: {integrity: sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==} - dev: false + '@openzeppelin/contracts-upgradeable@4.7.3': {} - /@openzeppelin/contracts-upgradeable@4.8.3: - resolution: {integrity: sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg==} - dev: false + '@openzeppelin/contracts-upgradeable@4.8.3': {} - /@openzeppelin/contracts-upgradeable@4.9.3: - resolution: {integrity: sha512-jjaHAVRMrE4UuZNfDwjlLGDxTHWIOwTJS2ldnc278a0gevfXfPr8hxKEVBGFBE96kl2G3VHDZhUimw/+G3TG2A==} - dev: false + '@openzeppelin/contracts-upgradeable@4.9.3': {} - /@openzeppelin/contracts@4.5.0: - resolution: {integrity: sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==} - dev: false + '@openzeppelin/contracts@4.5.0': {} - /@openzeppelin/contracts@4.7.3: - resolution: {integrity: sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==} - dev: false + '@openzeppelin/contracts@4.7.3': {} - /@openzeppelin/contracts@4.8.3: - resolution: {integrity: sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg==} - dev: false + '@openzeppelin/contracts@4.8.3': {} - /@openzeppelin/contracts@4.9.3: - resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} - dev: false + '@openzeppelin/contracts@4.9.3': {} - /@openzeppelin/upgrades-core@1.32.5: - resolution: {integrity: sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==} - hasBin: true - requiresBuild: true + '@openzeppelin/upgrades-core@1.32.5': dependencies: cbor: 9.0.2 chalk: 4.1.2 compare-versions: 6.1.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) ethereumjs-util: 7.1.5 minimist: 1.2.8 proper-lockfile: 4.1.2 solidity-ast: 0.4.56 transitivePeerDependencies: - supports-color - dev: false optional: true - /@pkgr/core@0.1.1: - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true + '@pkgr/core@0.1.1': {} - /@pnpm/config.env-replace@1.1.0: - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - dev: true + '@pnpm/config.env-replace@1.1.0': {} - /@pnpm/network.ca-file@1.0.2: - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} + '@pnpm/network.ca-file@1.0.2': dependencies: graceful-fs: 4.2.10 - dev: true - /@pnpm/npm-conf@2.2.2: - resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} - engines: {node: '>=12'} + '@pnpm/npm-conf@2.2.2': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - dev: true - /@prettier/sync@0.3.0(prettier@3.2.5): - resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} - peerDependencies: - prettier: ^3.0.0 + '@prettier/sync@0.3.0(prettier@3.2.5)': dependencies: prettier: 3.2.5 - dev: true - /@scroll-tech/contracts@0.1.0: - resolution: {integrity: sha512-aBbDOc3WB/WveZdpJYcrfvMYMz7ZTEiW8M9XMJLba8p9FAR5KGYB/cV+8+EUsq3MKt7C1BfR+WnXoTVdvwIY6w==} - dev: false + '@scroll-tech/contracts@0.1.0': {} - /@scure/base@1.1.1: - resolution: {integrity: sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==} - dev: true + '@scure/base@1.1.1': {} - /@scure/bip32@1.1.0: - resolution: {integrity: sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q==} + '@scure/bip32@1.1.0': dependencies: '@noble/hashes': 1.1.2 '@noble/secp256k1': 1.6.3 '@scure/base': 1.1.1 - dev: true - /@scure/bip39@1.1.0: - resolution: {integrity: sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==} + '@scure/bip39@1.1.0': dependencies: '@noble/hashes': 1.1.2 '@scure/base': 1.1.1 - dev: true - /@sentry/core@5.30.0: - resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} - engines: {node: '>=6'} + '@sentry/core@5.30.0': dependencies: '@sentry/hub': 5.30.0 '@sentry/minimal': 5.30.0 '@sentry/types': 5.30.0 '@sentry/utils': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/hub@5.30.0: - resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} - engines: {node: '>=6'} + '@sentry/hub@5.30.0': dependencies: '@sentry/types': 5.30.0 '@sentry/utils': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/minimal@5.30.0: - resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} - engines: {node: '>=6'} + '@sentry/minimal@5.30.0': dependencies: '@sentry/hub': 5.30.0 '@sentry/types': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/node@5.30.0: - resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} - engines: {node: '>=6'} + '@sentry/node@5.30.0': dependencies: '@sentry/core': 5.30.0 '@sentry/hub': 5.30.0 @@ -1406,94 +4484,54 @@ packages: tslib: 1.14.1 transitivePeerDependencies: - supports-color - dev: true - /@sentry/tracing@5.30.0: - resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} - engines: {node: '>=6'} + '@sentry/tracing@5.30.0': dependencies: '@sentry/hub': 5.30.0 '@sentry/minimal': 5.30.0 '@sentry/types': 5.30.0 '@sentry/utils': 5.30.0 tslib: 1.14.1 - dev: true - /@sentry/types@5.30.0: - resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} - engines: {node: '>=6'} - dev: true + '@sentry/types@5.30.0': {} - /@sentry/utils@5.30.0: - resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} - engines: {node: '>=6'} + '@sentry/utils@5.30.0': dependencies: '@sentry/types': 5.30.0 tslib: 1.14.1 - dev: true - /@sindresorhus/is@4.6.0: - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - dev: true + '@sindresorhus/is@4.6.0': {} - /@solidity-parser/parser@0.17.0: - resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} - dev: true + '@solidity-parser/parser@0.17.0': {} - /@solidity-parser/parser@0.18.0: - resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} - dev: true + '@solidity-parser/parser@0.18.0': {} - /@szmarczak/http-timer@5.0.1: - resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} - engines: {node: '>=14.16'} + '@szmarczak/http-timer@5.0.1': dependencies: defer-to-connect: 2.0.1 - dev: true - /@truffle/abi-utils@0.3.2: - resolution: {integrity: sha512-32queMD64YKL/tmQgSV4Xs073dIaZ9tp7NP1icjwvFSA3Q9yeu7ApYbSbYMsx9H9zWkkVOsfcoJ2kJEieOCzsA==} + '@truffle/abi-utils@0.3.2': dependencies: change-case: 3.0.2 fast-check: 3.1.1 web3-utils: 1.7.4 - dev: true - /@truffle/contract-schema@3.4.10: - resolution: {integrity: sha512-BhRNRoRvlj2th6E5RNS0BnS0ZxQe01JJz8I7MjkGqdeXSvrn6qDCAnbmvhNgUv0l5h8w5+gBOQhAJhILf1shdQ==} + '@truffle/contract-schema@3.4.10': dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true + '@tsconfig/node10@1.0.9': {} - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true + '@tsconfig/node12@1.0.11': {} - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true + '@tsconfig/node14@1.0.3': {} - /@tsconfig/node16@1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} - dev: true + '@tsconfig/node16@1.0.3': {} - /@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.4.5): - resolution: {integrity: sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==} - peerDependencies: - '@ethersproject/abi': ^5.0.0 - '@ethersproject/bytes': ^5.0.0 - '@ethersproject/providers': ^5.0.0 - ethers: ^5.1.3 - typechain: ^5.0.0 - typescript: '>=4.0.0' + '@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5)': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/bytes': 5.7.0 @@ -1503,153 +4541,92 @@ packages: ts-essentials: 7.0.3(typescript@5.4.5) typechain: 8.3.2(typescript@5.4.5) typescript: 5.4.5 - dev: true - /@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0)(ethers@5.7.2)(hardhat@2.20.1)(typechain@8.3.2): - resolution: {integrity: sha512-XB79i5ewg9Met7gMVGfgVkmypicbnI25T5clJBEooMoW2161p4zvKFpoS2O+lBppQyMrPIZkdvl2M3LMDayVcA==} - peerDependencies: - '@ethersproject/abi': ^5.4.7 - '@ethersproject/providers': ^5.4.7 - '@typechain/ethers-v5': ^11.0.0 - ethers: ^5.4.7 - hardhat: ^2.9.9 - typechain: ^8.2.0 + '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))(typechain@8.3.2(typescript@5.4.5))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2)(typescript@5.4.5) + '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) typechain: 8.3.2(typescript@5.4.5) - dev: true - /@types/bn.js@4.11.6: - resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + '@types/bn.js@4.11.6': dependencies: '@types/node': 20.12.12 - dev: true - /@types/bn.js@5.1.1: - resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} + '@types/bn.js@5.1.1': dependencies: '@types/node': 20.12.12 - /@types/cacheable-request@6.0.2: - resolution: {integrity: sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==} + '@types/cacheable-request@6.0.2': dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 '@types/node': 20.12.12 '@types/responselike': 1.0.0 - dev: true - /@types/cbor@5.0.1: - resolution: {integrity: sha512-zVqJy2KzusZPLOgyGJDnOIbu3DxIGGqxYbEwtEEe4Z+la8jwIhOyb+GMrlHafs5tvKruwf8f8qOYP6zTvse/pw==} + '@types/cbor@5.0.1': dependencies: '@types/node': 20.12.12 - dev: true - /@types/chai-as-promised@7.1.8: - resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} + '@types/chai-as-promised@7.1.8': dependencies: '@types/chai': 4.3.16 - dev: true - /@types/chai@4.3.16: - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} - dev: true + '@types/chai@4.3.16': {} - /@types/debug@4.1.12: - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.31 - dev: true - /@types/deep-equal-in-any-order@1.0.3: - resolution: {integrity: sha512-jT0O3hAILDKeKbdWJ9FZLD0Xdfhz7hMvfyFlRWpirjiEVr8G+GZ4kVIzPIqM6x6Rpp93TNPgOAed4XmvcuV6Qg==} - dev: true + '@types/deep-equal-in-any-order@1.0.3': {} - /@types/http-cache-semantics@4.0.1: - resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} - dev: true + '@types/http-cache-semantics@4.0.1': {} - /@types/keyv@3.1.4: - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/keyv@3.1.4': dependencies: '@types/node': 20.12.12 - dev: true - /@types/lru-cache@5.1.1: - resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - dev: true + '@types/lru-cache@5.1.1': {} - /@types/minimist@1.2.5: - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - dev: false + '@types/minimist@1.2.5': {} - /@types/mocha@10.0.6: - resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} - dev: true + '@types/mocha@10.0.6': {} - /@types/ms@0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: true + '@types/ms@0.7.31': {} - /@types/node@12.19.16: - resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} - dev: false + '@types/node@12.19.16': {} - /@types/node@20.12.12: - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} + '@types/node@20.12.12': dependencies: undici-types: 5.26.5 - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: false + '@types/normalize-package-data@2.4.4': {} - /@types/pbkdf2@3.1.0: - resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} + '@types/pbkdf2@3.1.0': dependencies: '@types/node': 20.12.12 - /@types/prettier@2.7.1: - resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} - dev: true + '@types/prettier@2.7.1': {} - /@types/readable-stream@2.3.15: - resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} + '@types/readable-stream@2.3.15': dependencies: '@types/node': 20.12.12 safe-buffer: 5.1.2 - dev: true - /@types/responselike@1.0.0: - resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} + '@types/responselike@1.0.0': dependencies: '@types/node': 20.12.12 - dev: true - /@types/secp256k1@4.0.3: - resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} + '@types/secp256k1@4.0.3': dependencies: '@types/node': 20.12.12 - /@types/semver@7.5.0: - resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} - dev: false + '@types/semver@7.5.0': {} - /@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) @@ -1662,92 +4639,59 @@ packages: ignore: 5.3.1 natural-compare: 1.4.0 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@typescript-eslint/scope-manager': 7.10.0 '@typescript-eslint/types': 7.10.0 '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.10.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/scope-manager@7.10.0: - resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@7.10.0': dependencies: '@typescript-eslint/types': 7.10.0 '@typescript-eslint/visitor-keys': 7.10.0 - dev: true - /@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/types@7.10.0: - resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true + '@typescript-eslint/types@7.10.0': {} - /@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5): - resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)': dependencies: '@typescript-eslint/types': 7.10.0 '@typescript-eslint/visitor-keys': 7.10.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - dev: true - /@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 + '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@typescript-eslint/scope-manager': 7.10.0 @@ -1757,27 +4701,17 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: true - /@typescript-eslint/visitor-keys@7.10.0: - resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@7.10.0': dependencies: '@typescript-eslint/types': 7.10.0 eslint-visitor-keys: 3.4.3 - dev: true - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true + '@ungap/structured-clone@1.2.0': {} - /@yarnpkg/lockfile@1.1.0: - resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} - dev: false + '@yarnpkg/lockfile@1.1.0': {} - /abi-to-sol@0.6.6: - resolution: {integrity: sha512-PRn81rSpv6NXFPYQSw7ujruqIP6UkwZ/XoFldtiqCX8+2kHVc73xVaUVvdbro06vvBVZiwnxhEIGdI4BRMwGHw==} - hasBin: true + abi-to-sol@0.6.6: dependencies: '@truffle/abi-utils': 0.3.2 '@truffle/contract-schema': 3.4.10 @@ -1791,196 +4725,109 @@ packages: prettier-plugin-solidity: 1.3.1(prettier@2.8.8) transitivePeerDependencies: - supports-color - dev: true - /acorn-jsx@5.3.2(acorn@8.11.3): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-jsx@5.3.2(acorn@8.11.3): dependencies: acorn: 8.11.3 - dev: true - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true + acorn-walk@8.2.0: {} - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + acorn@8.10.0: {} - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + acorn@8.11.3: {} - /adm-zip@0.4.16: - resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} - engines: {node: '>=0.3.0'} - dev: true + adm-zip@0.4.16: {} - /aes-js@3.0.0: - resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + aes-js@3.0.0: {} - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + agent-base@6.0.2: dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 - dev: true - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true - /ajv@8.11.0: - resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + ajv@8.11.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 uri-js: 4.4.1 - dev: true - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + ansi-align@3.0.1: dependencies: string-width: 4.2.3 - dev: true - /ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - dev: true + ansi-colors@4.1.1: {} - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} + ansi-colors@4.1.3: {} - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 - dev: true - /ansi-escapes@6.2.1: - resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} - engines: {node: '>=14.16'} - dev: true + ansi-escapes@6.2.1: {} - /ansi-regex@2.1.1: - resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} - engines: {node: '>=0.10.0'} - dev: true + ansi-regex@2.1.1: {} - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + ansi-regex@5.0.1: {} - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true + ansi-regex@6.0.1: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /antlr4@4.13.1-patch-1: - resolution: {integrity: sha512-OjFLWWLzDMV9rdFhpvroCWR4ooktNg9/nvVYSA5z28wuVpU36QUNuioR1XLnQtcjVlf8npjyz593PxnU/f/Cow==} - engines: {node: '>=16'} - dev: true + ansi-styles@6.2.1: {} - /anymatch@3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} - engines: {node: '>= 8'} + antlr4@4.13.1-patch-1: {} + + anymatch@3.1.2: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true + arg@4.1.3: {} - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 - dev: false - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true + argparse@2.0.1: {} - /array-back@3.1.0: - resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} - engines: {node: '>=6'} - dev: true + array-back@3.1.0: {} - /array-back@4.0.2: - resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} - engines: {node: '>=8'} - dev: true + array-back@4.0.2: {} - /array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + array-buffer-byte-length@1.0.0: dependencies: call-bind: 1.0.5 is-array-buffer: 3.0.2 - dev: false - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - requiresBuild: true + array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 is-array-buffer: 3.0.4 - dev: false optional: true - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} + array-union@2.1.0: {} - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -1988,22 +4835,16 @@ packages: es-errors: 1.3.0 es-object-atoms: 1.0.0 es-shim-unscopables: 1.0.2 - dev: false optional: true - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} + array.prototype.flat@1.3.2: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 es-shim-unscopables: 1.0.2 - dev: false - /arraybuffer.prototype.slice@1.0.2: - resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} - engines: {node: '>= 0.4'} + arraybuffer.prototype.slice@1.0.2: dependencies: array-buffer-byte-length: 1.0.0 call-bind: 1.0.5 @@ -2012,12 +4853,8 @@ packages: get-intrinsic: 1.2.2 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 - dev: false - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - requiresBuild: true + arraybuffer.prototype.slice@1.0.3: dependencies: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 @@ -2027,59 +4864,34 @@ packages: get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 - dev: false optional: true - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: false + arrify@1.0.1: {} - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + assertion-error@1.1.0: {} - /ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - dev: true + ast-parents@0.0.1: {} - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true + astral-regex@2.0.0: {} - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} + at-least-node@1.0.0: {} - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: false + available-typed-arrays@1.0.5: {} - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - dev: false optional: true - /balanced-match@1.0.0: - resolution: {integrity: sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==} + balanced-match@1.0.0: {} - /base-x@3.0.9: - resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + base-x@3.0.9: dependencies: safe-buffer: 5.2.1 - /bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + bech32@1.1.4: {} - /better-ajv-errors@0.8.2(ajv@6.12.6): - resolution: {integrity: sha512-FnODTBJSQSHmJXDLPiC7ca0dC4S1HSTPv1+Hg2sm/C71i3Dj0l1jcUEaq/3OQ6MmnUveshTsUvUj65pDSr3Qow==} - peerDependencies: - ajv: 4.11.8 - 8 + better-ajv-errors@0.8.2(ajv@6.12.6): dependencies: '@babel/code-frame': 7.18.6 '@babel/runtime': 7.24.0 @@ -2089,45 +4901,26 @@ packages: json-to-ast: 2.1.0 jsonpointer: 5.0.1 leven: 3.1.0 - dev: true - /better-path-resolve@1.0.0: - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} - engines: {node: '>=4'} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 - dev: false - /bigint-crypto-utils@3.3.0: - resolution: {integrity: sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==} - engines: {node: '>=14.0.0'} - dev: true + bigint-crypto-utils@3.3.0: {} - /bignumber.js@9.1.0: - resolution: {integrity: sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==} - dev: true + bignumber.js@9.1.0: {} - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true + binary-extensions@2.2.0: {} - /blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + blakejs@1.2.1: {} - /bn.js@4.11.6: - resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - dev: true + bn.js@4.11.6: {} - /bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + bn.js@4.12.0: {} - /bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + bn.js@5.2.1: {} - /boxen@5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} + boxen@5.1.2: dependencies: ansi-align: 3.0.1 camelcase: 6.3.0 @@ -2137,41 +4930,29 @@ packages: type-fest: 0.20.2 widest-line: 3.1.0 wrap-ansi: 7.0.0 - dev: true - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.0 concat-map: 0.0.1 - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.0 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - /breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + breakword@1.0.6: dependencies: wcwidth: 1.0.1 - dev: false - /brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + brorand@1.1.0: {} - /browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - dev: true + browser-stdout@1.3.1: {} - /browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 cipher-base: 1.0.4 @@ -2180,43 +4961,27 @@ packages: inherits: 2.0.4 safe-buffer: 5.2.1 - /bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + bs58@4.0.1: dependencies: base-x: 3.0.9 - /bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + bs58check@2.1.2: dependencies: bs58: 4.0.1 create-hash: 1.2.0 safe-buffer: 5.2.1 - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true + buffer-from@1.1.2: {} - /buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + buffer-xor@1.0.3: {} - /bufio@1.0.7: - resolution: {integrity: sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A==} - engines: {node: '>=8.0.0'} - dev: false + bufio@1.0.7: {} - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true + bytes@3.1.2: {} - /cacheable-lookup@6.1.0: - resolution: {integrity: sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==} - engines: {node: '>=10.6.0'} - dev: true + cacheable-lookup@6.1.0: {} - /cacheable-request@7.0.2: - resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} - engines: {node: '>=8'} + cacheable-request@7.0.2: dependencies: clone-response: 1.0.2 get-stream: 5.1.0 @@ -2225,96 +4990,59 @@ packages: lowercase-keys: 2.0.0 normalize-url: 6.1.0 responselike: 2.0.1 - dev: true - /call-bind@1.0.5: - resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + call-bind@1.0.5: dependencies: function-bind: 1.1.2 get-intrinsic: 1.2.2 set-function-length: 1.1.1 - dev: false - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - requiresBuild: true + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 get-intrinsic: 1.2.4 set-function-length: 1.2.2 - dev: false optional: true - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true + callsites@3.1.0: {} - /camel-case@3.0.0: - resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} + camel-case@3.0.0: dependencies: no-case: 2.3.2 upper-case: 1.1.3 - dev: true - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} + camelcase-keys@6.2.2: dependencies: camelcase: 5.3.1 map-obj: 4.3.0 quick-lru: 4.0.1 - dev: false - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: false + camelcase@5.3.1: {} - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true + camelcase@6.3.0: {} - /cbor@5.2.0: - resolution: {integrity: sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==} - engines: {node: '>=6.0.0'} + cbor@5.2.0: dependencies: bignumber.js: 9.1.0 nofilter: 1.0.4 - dev: true - /cbor@8.1.0: - resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} - engines: {node: '>=12.19'} + cbor@8.1.0: dependencies: nofilter: 3.1.0 - dev: true - /cbor@9.0.2: - resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} - engines: {node: '>=16'} - requiresBuild: true + cbor@9.0.2: dependencies: nofilter: 3.1.0 - dev: false optional: true - /chai-as-promised@7.1.1(chai@4.4.1): - resolution: {integrity: sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==} - peerDependencies: - chai: '>= 2.1.2 < 5' + chai-as-promised@7.1.1(chai@4.4.1): dependencies: chai: 4.4.1 check-error: 1.0.3 - dev: true - /chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} - engines: {node: '>=4'} + chai@4.4.1: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 @@ -2324,28 +5052,20 @@ packages: pathval: 1.1.1 type-detect: 4.0.8 - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true + chalk@5.3.0: {} - /change-case@3.0.2: - resolution: {integrity: sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==} + change-case@3.0.2: dependencies: camel-case: 3.0.0 constant-case: 2.0.0 @@ -2365,20 +5085,14 @@ packages: title-case: 2.1.1 upper-case: 1.1.3 upper-case-first: 1.1.2 - dev: true - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: false + chardet@0.7.0: {} - /check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + check-error@1.0.3: dependencies: get-func-name: 2.0.2 - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} + chokidar@3.5.3: dependencies: anymatch: 3.1.2 braces: 3.0.2 @@ -2389,192 +5103,118 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.2 - dev: true - /ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + ci-info@2.0.0: {} - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: false + ci-info@3.9.0: {} - /cipher-base@1.0.4: - resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + cipher-base@1.0.4: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true + clean-stack@2.2.0: {} - /cli-boxes@2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - dev: true + cli-boxes@2.2.1: {} - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-cursor@4.0.0: dependencies: restore-cursor: 4.0.0 - dev: true - /cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 string-width: 7.1.0 - dev: true - /cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + cliui@6.0.0: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - dev: false - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@7.0.4: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: false - /clone-response@1.0.2: - resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} + clone-response@1.0.2: dependencies: mimic-response: 1.0.1 - dev: true - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: false + clone@1.0.4: {} - /code-error-fragment@0.0.230: - resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==} - engines: {node: '>= 4'} - dev: true + code-error-fragment@0.0.230: {} - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@1.9.3: dependencies: color-name: 1.1.3 - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.3: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-name@1.1.4: {} - /colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true + colorette@2.0.20: {} - /command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - dev: true + command-exists@1.2.9: {} - /command-line-args@5.2.1: - resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} - engines: {node: '>=4.0.0'} + command-line-args@5.2.1: dependencies: array-back: 3.1.0 find-replace: 3.0.0 lodash.camelcase: 4.3.0 typical: 4.0.0 - dev: true - /command-line-usage@6.1.3: - resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} - engines: {node: '>=8.0.0'} + command-line-usage@6.1.3: dependencies: array-back: 4.0.2 chalk: 2.4.2 table-layout: 1.0.2 typical: 5.2.0 - dev: true - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true + commander@10.0.1: {} - /commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - dev: true + commander@11.1.0: {} - /commander@3.0.2: - resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - dev: true + commander@3.0.2: {} - /compare-versions@6.1.0: - resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} - requiresBuild: true - dev: false + compare-versions@6.1.0: optional: true - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-map@0.0.1: {} - /config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + config-chain@1.1.13: dependencies: ini: 1.3.8 proto-list: 1.2.4 - dev: true - /constant-case@2.0.0: - resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} + constant-case@2.0.0: dependencies: snake-case: 2.1.0 upper-case: 1.1.3 - dev: true - /cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - dev: true + cookie@0.4.2: {} - /core-js@3.30.1: - resolution: {integrity: sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==} - requiresBuild: true - dev: true + core-js@3.30.1: {} - /cosmiconfig@8.2.0: - resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} - engines: {node: '>=14'} + cosmiconfig@8.2.0: dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 - dev: true - /create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + create-hash@1.2.0: dependencies: cipher-base: 1.0.4 inherits: 2.0.4 @@ -2582,8 +5222,7 @@ packages: ripemd160: 2.0.2 sha.js: 2.4.11 - /create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + create-hmac@1.1.7: dependencies: cipher-base: 1.0.4 create-hash: 1.2.0 @@ -2592,264 +5231,151 @@ packages: safe-buffer: 5.2.1 sha.js: 2.4.11 - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true + create-require@1.1.1: {} - /cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + cross-spawn@5.1.0: dependencies: lru-cache: 4.1.5 shebang-command: 1.2.0 which: 1.3.1 - dev: false - /cross-spawn@6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} - engines: {node: '>=4.8'} + cross-spawn@6.0.5: dependencies: nice-try: 1.0.5 path-key: 2.0.1 semver: 5.7.1 shebang-command: 1.2.0 which: 1.3.1 - dev: false - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true - /csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - dev: false + csv-generate@3.4.3: {} - /csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - dev: false + csv-parse@4.16.3: {} - /csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - dev: false + csv-stringify@5.6.5: {} - /csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} + csv@5.5.3: dependencies: csv-generate: 3.4.3 csv-parse: 4.16.3 csv-stringify: 5.6.5 stream-transform: 2.1.3 - dev: false - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - requiresBuild: true + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false optional: true - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + data-view-byte-length@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false optional: true - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - requiresBuild: true + data-view-byte-offset@1.0.0: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false optional: true - /dataloader@1.4.0: - resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - dev: false - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 + dataloader@1.4.0: {} - /debug@4.3.4(supports-color@8.1.1): - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4(supports-color@8.1.1): dependencies: ms: 2.1.2 + optionalDependencies: supports-color: 8.1.1 - dev: true - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 map-obj: 1.0.1 - dev: false - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: false + decamelize@1.2.0: {} - /decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - dev: true + decamelize@4.0.0: {} - /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 - dev: true - /deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} + deep-eql@4.1.3: dependencies: type-detect: 4.0.8 - /deep-equal-in-any-order@2.0.6: - resolution: {integrity: sha512-RfnWHQzph10YrUjvWwhd15Dne8ciSJcZ3U6OD7owPwiVwsdE5IFSoZGg8rlwJD11ES+9H5y8j3fCofviRHOqLQ==} + deep-equal-in-any-order@2.0.6: dependencies: lodash.mapvalues: 4.6.0 sort-any: 2.0.0 - dev: true - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true + deep-extend@0.6.0: {} - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true + deep-is@0.1.4: {} - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + defaults@1.0.4: dependencies: clone: 1.0.4 - dev: false - /defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} - dev: true + defer-to-connect@2.0.1: {} - /define-data-property@1.1.1: - resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} - engines: {node: '>= 0.4'} + define-data-property@1.1.1: dependencies: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: false - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 - dev: false optional: true - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} + define-properties@1.2.1: dependencies: define-data-property: 1.1.1 has-property-descriptors: 1.0.0 object-keys: 1.1.1 - dev: false - /delete-empty@3.0.0: - resolution: {integrity: sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ==} - engines: {node: '>=10'} - hasBin: true + delete-empty@3.0.0: dependencies: ansi-colors: 4.1.3 minimist: 1.2.8 path-starts-with: 2.0.1 rimraf: 2.7.1 - dev: true - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true + depd@2.0.0: {} - /detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: false + detect-indent@6.1.0: {} - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true + diff@4.0.2: {} - /diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - dev: true + diff@5.0.0: {} - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} + doctrine@3.0.0: dependencies: esutils: 2.0.3 - dev: true - /dot-case@2.1.1: - resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} + dot-case@2.1.1: dependencies: no-case: 2.3.2 - dev: true - /dotenv@8.6.0: - resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} - engines: {node: '>=10'} - dev: false + dotenv@8.6.0: {} - /elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + elliptic@6.5.4: dependencies: bn.js: 4.12.0 brorand: 1.1.0 @@ -2859,38 +5385,25 @@ packages: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - /emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - dev: true + emoji-regex@10.3.0: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@8.0.0: {} - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + end-of-stream@1.4.4: dependencies: once: 1.4.0 - dev: true - /enquirer@2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} + enquirer@2.3.6: dependencies: ansi-colors: 4.1.3 - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: true + env-paths@2.2.1: {} - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - /es-abstract@1.22.3: - resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} - engines: {node: '>= 0.4'} + es-abstract@1.22.3: dependencies: array-buffer-byte-length: 1.0.0 arraybuffer.prototype.slice: 1.0.2 @@ -2931,12 +5444,8 @@ packages: typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.13 - dev: false - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - requiresBuild: true + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 @@ -2984,129 +5493,71 @@ packages: typed-array-length: 1.0.6 unbox-primitive: 1.0.2 which-typed-array: 1.1.15 - dev: false optional: true - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + es-define-property@1.0.0: dependencies: get-intrinsic: 1.2.4 - dev: false optional: true - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - requiresBuild: true - dev: false + es-errors@1.3.0: optional: true - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - requiresBuild: true + es-object-atoms@1.0.0: dependencies: es-errors: 1.3.0 - dev: false optional: true - /es-set-tostringtag@2.0.2: - resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} - engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.2: dependencies: get-intrinsic: 1.2.2 has-tostringtag: 1.0.0 hasown: 2.0.0 - dev: false - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + es-set-tostringtag@2.0.3: dependencies: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 hasown: 2.0.2 - dev: false optional: true - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + es-shim-unscopables@1.0.2: dependencies: hasown: 2.0.0 - dev: false - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.2 is-symbol: 1.0.3 - dev: false - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} + escalade@3.1.1: {} - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} + escape-string-regexp@1.0.5: {} - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true + escape-string-regexp@4.0.0: {} - /eslint-config-prettier@9.1.0(eslint@8.57.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' + eslint-config-prettier@9.1.0(eslint@8.57.0): dependencies: eslint: 8.57.0 - dev: true - /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5): - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '*' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true + eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): dependencies: eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) prettier: 3.2.5 prettier-linter-helpers: 1.0.0 synckit: 0.8.8 - dev: true + optionalDependencies: + eslint-config-prettier: 9.1.0(eslint@8.57.0) - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - dev: true - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true + eslint-visitor-keys@3.4.3: {} - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true + eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/regexpp': 4.10.0 @@ -3119,7 +5570,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -3148,55 +5599,32 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color - dev: true - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + espree@9.6.1: dependencies: acorn: 8.11.3 acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 - dev: true - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: false + esprima@4.0.1: {} - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} + esquery@1.5.0: dependencies: estraverse: 5.3.0 - dev: true - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 - dev: true - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true + estraverse@5.3.0: {} - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true + esutils@2.0.3: {} - /ethereum-bloom-filters@1.0.10: - resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} + ethereum-bloom-filters@1.0.10: dependencies: js-sha3: 0.8.0 - dev: true - /ethereum-cryptography@0.1.3: - resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + ethereum-cryptography@0.1.3: dependencies: '@types/pbkdf2': 3.1.0 '@types/secp256k1': 4.0.3 @@ -3214,24 +5642,19 @@ packages: secp256k1: 4.0.3 setimmediate: 1.0.5 - /ethereum-cryptography@1.1.2: - resolution: {integrity: sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==} + ethereum-cryptography@1.1.2: dependencies: '@noble/hashes': 1.1.2 '@noble/secp256k1': 1.6.3 '@scure/bip32': 1.1.0 '@scure/bip39': 1.1.0 - dev: true - /ethereumjs-abi@0.6.8: - resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + ethereumjs-abi@0.6.8: dependencies: bn.js: 4.12.0 ethereumjs-util: 6.2.1 - dev: true - /ethereumjs-util@6.2.1: - resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + ethereumjs-util@6.2.1: dependencies: '@types/bn.js': 4.11.6 bn.js: 4.12.0 @@ -3240,11 +5663,8 @@ packages: ethereum-cryptography: 0.1.3 ethjs-util: 0.1.6 rlp: 2.2.7 - dev: true - /ethereumjs-util@7.1.5: - resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} - engines: {node: '>=10.0.0'} + ethereumjs-util@7.1.5: dependencies: '@types/bn.js': 5.1.1 bn.js: 5.2.1 @@ -3252,8 +5672,7 @@ packages: ethereum-cryptography: 0.1.3 rlp: 2.2.7 - /ethers@5.7.2: - resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} + ethers@5.7.2: dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-provider': 5.7.0 @@ -3289,35 +5708,24 @@ packages: - bufferutil - utf-8-validate - /ethjs-unit@0.1.6: - resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} - engines: {node: '>=6.5.0', npm: '>=3'} + ethjs-unit@0.1.6: dependencies: bn.js: 4.11.6 number-to-bn: 1.7.0 - dev: true - /ethjs-util@0.1.6: - resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} - engines: {node: '>=6.5.0', npm: '>=3'} + ethjs-util@0.1.6: dependencies: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 - dev: true - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: true + eventemitter3@5.0.1: {} - /evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + evp_bytestokey@1.0.3: dependencies: md5.js: 1.3.5 safe-buffer: 5.2.1 - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} + execa@8.0.1: dependencies: cross-spawn: 7.0.3 get-stream: 8.0.1 @@ -3328,39 +5736,24 @@ packages: onetime: 6.0.0 signal-exit: 4.1.0 strip-final-newline: 3.0.0 - dev: true - /extendable-error@0.1.7: - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - dev: false + extendable-error@0.1.7: {} - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} + external-editor@3.1.0: dependencies: chardet: 0.7.0 iconv-lite: 0.4.24 tmp: 0.0.33 - dev: false - /fast-check@3.1.1: - resolution: {integrity: sha512-3vtXinVyuUKCKFKYcwXhGE6NtGWkqF8Yh3rvMZNzmwz8EPrgoc/v4pDdLHyLnCyCI5MZpZZkDEwFyXyEONOxpA==} - engines: {node: '>=8.0.0'} + fast-check@3.1.1: dependencies: pure-rand: 5.0.3 - dev: true - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true + fast-deep-equal@3.1.3: {} - /fast-diff@1.2.0: - resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - dev: true + fast-diff@1.2.0: {} - /fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} + fast-glob@3.3.1: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 @@ -3368,268 +5761,165 @@ packages: merge2: 1.4.1 micromatch: 4.0.5 - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true + fast-json-stable-stringify@2.1.0: {} - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true + fast-levenshtein@2.0.6: {} - /fastq@1.6.0: - resolution: {integrity: sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==} + fastq@1.6.0: dependencies: reusify: 1.0.4 - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 - dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - /find-replace@3.0.0: - resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} - engines: {node: '>=4.0.0'} + find-replace@3.0.0: dependencies: array-back: 3.1.0 - dev: true - /find-up@2.1.0: - resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} - engines: {node: '>=4'} + find-up@2.1.0: dependencies: locate-path: 2.0.0 - dev: true - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: false - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - /find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + find-yarn-workspace-root2@1.2.16: dependencies: micromatch: 4.0.5 pkg-dir: 4.2.0 - dev: false - /find-yarn-workspace-root@2.0.0: - resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==} + find-yarn-workspace-root@2.0.0: dependencies: micromatch: 4.0.5 - dev: false - /flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@3.2.0: dependencies: flatted: 3.3.1 keyv: 4.5.4 rimraf: 3.0.2 - dev: true - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true + flat@5.0.2: {} - /flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - dev: true + flatted@3.3.1: {} - /follow-redirects@1.15.6(debug@4.3.4): - resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: - debug: 4.3.4 - dev: true + follow-redirects@1.15.6(debug@4.3.4): + optionalDependencies: + debug: 4.3.4(supports-color@8.1.1) - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.3: dependencies: is-callable: 1.2.7 - dev: false - /form-data-encoder@1.7.1: - resolution: {integrity: sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==} - dev: true + form-data-encoder@1.7.1: {} - /fp-ts@1.19.3: - resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} - dev: true + fp-ts@1.19.3: {} - /fs-extra@0.30.0: - resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} + fs-extra@0.30.0: dependencies: graceful-fs: 4.2.10 jsonfile: 2.4.0 klaw: 1.3.1 path-is-absolute: 1.0.1 rimraf: 2.7.1 - dev: true - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.10 jsonfile: 4.0.0 universalify: 0.1.2 - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.10 jsonfile: 4.0.0 universalify: 0.1.2 - dev: false - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} + fs-extra@9.1.0: dependencies: at-least-node: 1.0.0 graceful-fs: 4.2.10 jsonfile: 6.1.0 universalify: 2.0.0 - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fs.realpath@1.0.0: {} - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fsevents@2.3.2: optional: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: false + function-bind@1.1.2: {} - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} + function.prototype.name@1.1.6: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 functions-have-names: 1.2.3 - dev: false - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: false + functions-have-names@1.2.3: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} + get-caller-file@2.0.5: {} - /get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} - engines: {node: '>=18'} - dev: true + get-east-asian-width@1.2.0: {} - /get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + get-func-name@2.0.2: {} - /get-intrinsic@1.2.2: - resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + get-intrinsic@1.2.2: dependencies: function-bind: 1.1.2 has-proto: 1.0.1 has-symbols: 1.0.3 hasown: 2.0.0 - dev: false - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 has-proto: 1.0.1 has-symbols: 1.0.3 hasown: 2.0.0 - dev: false optional: true - /get-stream@5.1.0: - resolution: {integrity: sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==} - engines: {node: '>=8'} + get-stream@5.1.0: dependencies: pump: 3.0.0 - dev: true - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true + get-stream@6.0.1: {} - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: true + get-stream@8.0.1: {} - /get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 - dev: false - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - requiresBuild: true + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - dev: false optional: true - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - dev: true - /glob@7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + glob@7.1.7: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -3637,10 +5927,8 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + glob@7.2.0: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -3648,10 +5936,8 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + glob@7.2.3: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -3660,34 +5946,23 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} + glob@8.1.0: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 minimatch: 5.1.6 once: 1.4.0 - dev: true - /globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} + globals@13.24.0: dependencies: type-fest: 0.20.2 - dev: true - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} + globalthis@1.0.3: dependencies: define-properties: 1.2.1 - dev: false - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -3696,15 +5971,11 @@ packages: merge2: 1.4.1 slash: 3.0.0 - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.0.1: dependencies: get-intrinsic: 1.2.2 - dev: false - /got@12.1.0: - resolution: {integrity: sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==} - engines: {node: '>=14.16'} + got@12.1.0: dependencies: '@sindresorhus/is': 4.6.0 '@szmarczak/http-timer': 5.0.1 @@ -3719,53 +5990,28 @@ packages: lowercase-keys: 3.0.0 p-cancelable: 3.0.0 responselike: 2.0.1 - dev: true - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + graceful-fs@4.2.10: {} - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + grapheme-splitter@1.0.4: {} - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true + graphemer@1.4.0: {} - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: false + hard-rejection@2.1.0: {} - /hardhat-abi-exporter@2.10.1(hardhat@2.20.1): - resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} - engines: {node: '>=14.14.0'} - peerDependencies: - hardhat: ^2.0.0 + hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)): dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.4.5) - dev: true + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) - /hardhat-ignore-warnings@0.2.11: - resolution: {integrity: sha512-+nHnRbP6COFZaXE7HAY7TZNE3au5vHe5dkcnyq0XaP07ikT2fJ3NhFY0vn7Deh4Qbz0Z/9Xpnj2ki6Ktgk61pg==} + hardhat-ignore-warnings@0.2.11: dependencies: minimatch: 5.1.6 node-interval-tree: 2.1.2 solidity-comments: 0.0.2 - dev: true - /hardhat@2.20.1(ts-node@10.9.2)(typescript@5.4.5): - resolution: {integrity: sha512-q75xDQiQtCZcTMBwjTovrXEU5ECr49baxr4/OBkIu/ULTPzlB20yk1dRWNmD2IFbAeAeXggaWvQAdpiScaHtPw==} - hasBin: true - peerDependencies: - ts-node: '*' - typescript: '*' - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true + hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -3791,7 +6037,7 @@ packages: chalk: 2.4.2 chokidar: 3.5.3 ci-info: 2.0.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) enquirer: 2.3.6 env-paths: 2.2.1 ethereum-cryptography: 1.1.2 @@ -3813,671 +6059,394 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) tsort: 0.0.1 - typescript: 5.4.5 undici: 5.28.4 uuid: 8.3.2 ws: 7.5.9 + optionalDependencies: + ts-node: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) + typescript: 5.4.5 transitivePeerDependencies: - bufferutil - c-kzg - supports-color - utf-8-validate - dev: true - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: false + has-bigints@1.0.2: {} - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + has-flag@3.0.0: {} - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + has-flag@4.0.0: {} - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + has-property-descriptors@1.0.0: dependencies: get-intrinsic: 1.2.2 - dev: false - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - requiresBuild: true + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 - dev: false optional: true - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: false + has-proto@1.0.1: {} - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - requiresBuild: true - dev: false + has-proto@1.0.3: optional: true - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false + has-symbols@1.0.3: {} - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} + has-tostringtag@1.0.0: dependencies: has-symbols: 1.0.3 - dev: false - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - requiresBuild: true + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 - dev: false optional: true - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + has@1.0.3: dependencies: function-bind: 1.1.2 - dev: false - /hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} + hash-base@3.1.0: dependencies: inherits: 2.0.4 readable-stream: 3.6.0 safe-buffer: 5.2.1 - /hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + hash.js@1.1.7: dependencies: inherits: 2.0.4 minimalistic-assert: 1.0.1 - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} + hasown@2.0.0: dependencies: function-bind: 1.1.2 - dev: false - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + hasown@2.0.2: dependencies: function-bind: 1.1.2 - dev: false optional: true - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true + he@1.2.0: {} - /header-case@1.0.1: - resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} + header-case@1.0.1: dependencies: no-case: 2.3.2 upper-case: 1.1.3 - dev: true - /hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + hmac-drbg@1.0.1: dependencies: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: false + hosted-git-info@2.8.9: {} - /http-cache-semantics@4.0.3: - resolution: {integrity: sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==} - dev: true + http-cache-semantics@4.0.3: {} - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} + http-errors@2.0.0: dependencies: depd: 2.0.0 inherits: 2.0.4 setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 - dev: true - /http2-wrapper@2.1.11: - resolution: {integrity: sha512-aNAk5JzLturWEUiuhAN73Jcbq96R7rTitAoXV54FYMatvihnpD2+6PUgU4ce3D/m5VDbw+F5CsyKSF176ptitQ==} - engines: {node: '>=10.19.0'} + http2-wrapper@2.1.11: dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - dev: true - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true - /human-id@1.0.2: - resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - dev: false + human-id@1.0.2: {} - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: true + human-signals@5.0.0: {} - /husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} - engines: {node: '>=18'} - hasBin: true - dev: true + husky@9.0.11: {} - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} + ignore@5.2.4: {} - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true + ignore@5.3.1: {} - /immutable@4.1.0: - resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} - dev: true + immutable@4.1.0: {} - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true + imurmurhash@0.1.4: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} + indent-string@4.0.0: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inherits@2.0.4: {} - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true + ini@1.3.8: {} - /internal-slot@1.0.6: - resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} - engines: {node: '>= 0.4'} + internal-slot@1.0.6: dependencies: get-intrinsic: 1.2.2 hasown: 2.0.0 side-channel: 1.0.4 - dev: false - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - requiresBuild: true + internal-slot@1.0.7: dependencies: es-errors: 1.3.0 hasown: 2.0.2 side-channel: 1.0.4 - dev: false optional: true - /io-ts@1.10.4: - resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} + io-ts@1.10.4: dependencies: fp-ts: 1.19.3 - dev: true - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + is-array-buffer@3.0.2: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-typed-array: 1.1.12 - dev: false - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - requiresBuild: true + + is-array-buffer@3.0.4: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 - dev: false optional: true - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.2.1: {} - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 - dev: false - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.2.0 - dev: true - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-boolean-object@1.1.2: dependencies: call-bind: 1.0.5 has-tostringtag: 1.0.0 - dev: false - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: false + is-callable@1.2.7: {} - /is-ci@2.0.0: - resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} - hasBin: true + is-ci@2.0.0: dependencies: ci-info: 2.0.0 - dev: false - /is-core-module@2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} + is-core-module@2.10.0: dependencies: has: 1.0.3 - dev: false - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - requiresBuild: true + is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 - dev: false optional: true - /is-date-object@1.0.2: - resolution: {integrity: sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==} - engines: {node: '>= 0.4'} - dev: false + is-date-object@1.0.2: {} - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: false + is-docker@2.2.1: {} - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} + is-fullwidth-code-point@3.0.0: {} - /is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - dev: true + is-fullwidth-code-point@4.0.0: {} - /is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} + is-fullwidth-code-point@5.0.0: dependencies: get-east-asian-width: 1.2.0 - dev: true - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - /is-hex-prefixed@1.0.0: - resolution: {integrity: sha1-fY035q135dEnFIkTxXPggtd39VQ=} - engines: {node: '>=6.5.0', npm: '>=3'} - dev: true + is-hex-prefixed@1.0.0: {} - /is-lower-case@1.1.3: - resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} + is-lower-case@1.1.3: dependencies: lower-case: 1.1.4 - dev: true - /is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: false + is-negative-zero@2.0.2: {} - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - requiresBuild: true - dev: false + is-negative-zero@2.0.3: optional: true - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.0 - dev: false - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + is-number@7.0.0: {} - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true + is-path-inside@3.0.3: {} - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: false + is-plain-obj@1.1.0: {} - /is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - dev: true + is-plain-obj@2.1.0: {} - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + is-regex@1.1.4: dependencies: call-bind: 1.0.5 has-tostringtag: 1.0.0 - dev: false - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + is-shared-array-buffer@1.0.2: dependencies: call-bind: 1.0.5 - dev: false - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - requiresBuild: true + is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 - dev: false optional: true - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + is-stream@3.0.0: {} - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 - dev: false - /is-subdir@1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 - dev: false - /is-symbol@1.0.3: - resolution: {integrity: sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==} - engines: {node: '>= 0.4'} + is-symbol@1.0.3: dependencies: has-symbols: 1.0.3 - dev: false - /is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} - engines: {node: '>= 0.4'} + is-typed-array@1.1.12: dependencies: which-typed-array: 1.1.13 - dev: false - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - requiresBuild: true + is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 - dev: false optional: true - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true + is-unicode-supported@0.1.0: {} - /is-upper-case@1.1.2: - resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} + is-upper-case@1.1.2: dependencies: upper-case: 1.1.3 - dev: true - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakref@1.0.2: dependencies: call-bind: 1.0.5 - dev: false - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: false + is-windows@1.0.2: {} - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} + is-wsl@2.2.0: dependencies: is-docker: 2.2.1 - dev: false - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: false + isarray@2.0.5: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isexe@2.0.0: {} - /js-sdsl@4.4.2: - resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==} - dev: true + js-sdsl@4.4.2: {} - /js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + js-sha3@0.8.0: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@4.0.0: {} - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true + js-yaml@3.14.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - dev: false - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - dev: true - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true + json-buffer@3.0.1: {} - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-parse-even-better-errors@2.3.1: {} - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true + json-schema-traverse@0.4.1: {} - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true + json-schema-traverse@1.0.0: {} - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true + json-stable-stringify-without-jsonify@1.0.1: {} - /json-to-ast@2.1.0: - resolution: {integrity: sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==} - engines: {node: '>= 4'} + json-to-ast@2.1.0: dependencies: code-error-fragment: 0.0.230 grapheme-splitter: 1.0.4 - dev: true - /jsonfile@2.4.0: - resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} + jsonfile@2.4.0: optionalDependencies: graceful-fs: 4.2.10 - dev: true - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.10 - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonfile@6.1.0: dependencies: universalify: 2.0.0 optionalDependencies: graceful-fs: 4.2.10 - /jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} - dev: true + jsonpointer@5.0.1: {} - /keccak@3.0.2: - resolution: {integrity: sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==} - engines: {node: '>=10.0.0'} - requiresBuild: true + keccak@3.0.2: dependencies: node-addon-api: 2.0.2 node-gyp-build: 4.5.0 readable-stream: 3.6.0 - /keyv@4.5.0: - resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} + keyv@4.5.0: dependencies: json-buffer: 3.0.1 - dev: true - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 - dev: true - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: false + kind-of@6.0.3: {} - /klaw-sync@6.0.0: - resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} + klaw-sync@6.0.0: dependencies: graceful-fs: 4.2.10 - dev: false - /klaw@1.3.1: - resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} + klaw@1.3.1: optionalDependencies: graceful-fs: 4.2.10 - dev: true - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: false + kleur@4.1.5: {} - /latest-version@7.0.0: - resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} - engines: {node: '>=14.16'} + latest-version@7.0.0: dependencies: package-json: 8.1.1 - dev: true - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true + leven@3.1.0: {} - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true - /lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} - engines: {node: '>=14'} - dev: true + lilconfig@3.0.0: {} - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lines-and-columns@1.2.4: {} - /lint-staged@15.2.2: - resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} - engines: {node: '>=18.12.0'} - hasBin: true + lint-staged@15.2.2: dependencies: chalk: 5.3.0 commander: 11.1.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) execa: 8.0.1 lilconfig: 3.0.0 listr2: 8.0.1 @@ -4487,11 +6456,8 @@ packages: yaml: 2.3.4 transitivePeerDependencies: - supports-color - dev: true - /listr2@8.0.1: - resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} - engines: {node: '>=18.0.0'} + listr2@8.0.1: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 @@ -4499,160 +6465,94 @@ packages: log-update: 6.0.0 rfdc: 1.3.1 wrap-ansi: 9.0.0 - dev: true - /load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} + load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.10 js-yaml: 3.14.1 pify: 4.0.1 strip-bom: 3.0.0 - dev: false - /locate-path@2.0.0: - resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} - engines: {node: '>=4'} + locate-path@2.0.0: dependencies: p-locate: 2.0.0 path-exists: 3.0.0 - dev: true - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - dev: false - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - /lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: true + lodash.camelcase@4.3.0: {} - /lodash.clonedeep@4.5.0: - resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} - dev: true + lodash.clonedeep@4.5.0: {} - /lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - dev: true + lodash.isequal@4.5.0: {} - /lodash.mapvalues@4.6.0: - resolution: {integrity: sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==} - dev: true + lodash.mapvalues@4.6.0: {} - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true + lodash.merge@4.6.2: {} - /lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - dev: false + lodash.startcase@4.4.0: {} - /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true + lodash.truncate@4.4.2: {} - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true + lodash@4.17.21: {} - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 is-unicode-supported: 0.1.0 - dev: true - /log-update@6.0.0: - resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} - engines: {node: '>=18'} + log-update@6.0.0: dependencies: ansi-escapes: 6.2.1 cli-cursor: 4.0.0 slice-ansi: 7.1.0 strip-ansi: 7.1.0 wrap-ansi: 9.0.0 - dev: true - /loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + loupe@2.3.7: dependencies: get-func-name: 2.0.2 - /lower-case-first@1.0.2: - resolution: {integrity: sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA==} + lower-case-first@1.0.2: dependencies: lower-case: 1.1.4 - dev: true - /lower-case@1.1.4: - resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} - dev: true + lower-case@1.1.4: {} - /lowercase-keys@2.0.0: - resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} - engines: {node: '>=8'} - dev: true + lowercase-keys@2.0.0: {} - /lowercase-keys@3.0.0: - resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + lowercase-keys@3.0.0: {} - /lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - dev: true + lru-cache@10.2.2: {} - /lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 yallist: 2.1.2 - dev: false - /lru_map@0.3.3: - resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} - dev: true + lru_map@0.3.3: {} - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true + make-error@1.3.6: {} - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: false + map-obj@1.0.1: {} - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: false + map-obj@4.3.0: {} - /md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + md5.js@1.3.5: dependencies: hash-base: 3.1.0 inherits: 2.0.4 safe-buffer: 5.2.1 - /memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - dev: true + memorystream@0.3.1: {} - /meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} + meow@6.1.1: dependencies: '@types/minimist': 1.2.5 camelcase-keys: 6.2.2 @@ -4665,114 +6565,63 @@ packages: trim-newlines: 3.0.1 type-fest: 0.13.1 yargs-parser: 18.1.3 - dev: false - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true + merge-stream@2.0.0: {} - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + merge2@1.4.1: {} - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromatch@4.0.5: dependencies: braces: 3.0.2 picomatch: 2.3.1 - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true + mimic-fn@2.1.0: {} - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true + mimic-fn@4.0.0: {} - /mimic-response@1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} - requiresBuild: true - dev: true + mimic-response@1.0.1: {} - /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - dev: true + mimic-response@3.1.0: {} - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: false + min-indent@1.0.1: {} - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + minimalistic-assert@1.0.1: {} - /minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + minimalistic-crypto-utils@1.0.1: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - /minimatch@5.0.1: - resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} - engines: {node: '>=10'} + minimatch@5.0.1: dependencies: brace-expansion: 2.0.1 - dev: true - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} + minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 - dev: true - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} + minimist-options@4.1.0: dependencies: arrify: 1.0.1 is-plain-obj: 1.1.0 kind-of: 6.0.3 - dev: false - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minimist@1.2.8: {} - /mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - dev: false + mixme@0.5.10: {} - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true + mkdirp@1.0.4: {} - /mnemonist@0.38.5: - resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} + mnemonist@0.38.5: dependencies: obliterator: 2.0.4 - dev: true - /mocha@10.2.0: - resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} - engines: {node: '>= 14.0.0'} - hasBin: true + mocha@10.2.0: dependencies: ansi-colors: 4.1.1 browser-stdout: 1.3.1 @@ -4795,179 +6644,102 @@ packages: yargs: 16.2.0 yargs-parser: 20.2.4 yargs-unparser: 2.0.0 - dev: true - /moment@2.30.1: - resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - dev: true + moment@2.30.1: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.2: {} - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true + ms@2.1.3: {} - /nanoid@3.3.3: - resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true + nanoid@3.3.3: {} - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true + natural-compare@1.4.0: {} - /neodoc@2.0.2: - resolution: {integrity: sha512-NAppJ0YecKWdhSXFYCHbo6RutiX8vOt/Jo3l46mUg6pQlpJNaqc5cGxdrW2jITQm5JIYySbFVPDl3RrREXNyPw==} + neodoc@2.0.2: dependencies: ansi-regex: 2.1.1 - dev: true - /nice-try@1.0.5: - resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - dev: false + nice-try@1.0.5: {} - /no-case@2.3.2: - resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} + no-case@2.3.2: dependencies: lower-case: 1.1.4 - dev: true - /node-addon-api@2.0.2: - resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + node-addon-api@2.0.2: {} - /node-fetch@2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true + node-fetch@2.6.7: dependencies: whatwg-url: 5.0.0 - dev: false - /node-gyp-build@4.5.0: - resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==} - hasBin: true + node-gyp-build@4.5.0: {} - /node-interval-tree@2.1.2: - resolution: {integrity: sha512-bJ9zMDuNGzVQg1xv0bCPzyEDxHgbrx7/xGj6CDokvizZZmastPsOh0JJLuY8wA5q2SfX1TLNMk7XNV8WxbGxzA==} - engines: {node: '>= 14.0.0'} + node-interval-tree@2.1.2: dependencies: shallowequal: 1.1.0 - dev: true - /nofilter@1.0.4: - resolution: {integrity: sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA==} - engines: {node: '>=8'} - dev: true + nofilter@1.0.4: {} - /nofilter@3.1.0: - resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} - engines: {node: '>=12.19'} + nofilter@3.1.0: {} - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 resolve: 1.22.1 semver: 5.7.1 validate-npm-package-license: 3.0.4 - dev: false - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true + normalize-path@3.0.0: {} - /normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - dev: true + normalize-url@6.1.0: {} - /npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 - dev: true - /number-to-bn@1.7.0: - resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} - engines: {node: '>=6.5.0', npm: '>=3'} + number-to-bn@1.7.0: dependencies: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - dev: true - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: false + object-inspect@1.13.1: {} - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: false + object-keys@1.1.1: {} - /object.assign@4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} + object.assign@4.1.4: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: false - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + object.assign@4.1.5: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: false optional: true - /obliterator@2.0.4: - resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} - dev: true + obliterator@2.0.4: {} - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + once@1.4.0: dependencies: wrappy: 1.0.2 - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 - dev: true - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 - dev: true - /open@7.4.2: - resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} - engines: {node: '>=8'} + open@7.4.2: dependencies: is-docker: 2.2.1 is-wsl: 2.2.0 - dev: false - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} + optionator@0.9.3: dependencies: '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 @@ -4975,137 +6747,81 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 - dev: true - /ordinal@1.0.3: - resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} - dev: true + ordinal@1.0.3: {} - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} + os-tmpdir@1.0.2: {} - /outdent@0.5.0: - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - dev: false + outdent@0.5.0: {} - /p-cancelable@3.0.0: - resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} - engines: {node: '>=12.20'} - dev: true + p-cancelable@3.0.0: {} - /p-filter@2.1.0: - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} - engines: {node: '>=8'} + p-filter@2.1.0: dependencies: p-map: 2.1.0 - dev: false - /p-limit@1.3.0: - resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} - engines: {node: '>=4'} + p-limit@1.3.0: dependencies: p-try: 1.0.0 - dev: true - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: false - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - /p-locate@2.0.0: - resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} - engines: {node: '>=4'} + p-locate@2.0.0: dependencies: p-limit: 1.3.0 - dev: true - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: false - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - /p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - dev: false + p-map@2.1.0: {} - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} + p-map@4.0.0: dependencies: aggregate-error: 3.1.0 - dev: true - /p-try@1.0.0: - resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} - engines: {node: '>=4'} - dev: true + p-try@1.0.0: {} - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: false + p-try@2.2.0: {} - /package-json@8.1.1: - resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} - engines: {node: '>=14.16'} + package-json@8.1.1: dependencies: got: 12.1.0 registry-auth-token: 5.0.2 registry-url: 6.0.1 semver: 7.6.2 - dev: true - /param-case@2.1.1: - resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} + param-case@2.1.1: dependencies: no-case: 2.3.2 - dev: true - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + parent-module@1.0.1: dependencies: callsites: 3.1.0 - dev: true - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.18.6 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - /pascal-case@2.0.1: - resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} + pascal-case@2.0.1: dependencies: camel-case: 3.0.0 upper-case-first: 1.1.2 - dev: true - /patch-package@6.5.1: - resolution: {integrity: sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==} - engines: {node: '>=10', npm: '>5'} - hasBin: true + patch-package@6.5.1: dependencies: '@yarnpkg/lockfile': 1.1.0 chalk: 4.1.2 @@ -5121,60 +6837,32 @@ packages: slash: 2.0.0 tmp: 0.0.33 yaml: 1.10.2 - dev: false - /path-case@2.1.1: - resolution: {integrity: sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q==} + path-case@2.1.1: dependencies: no-case: 2.3.2 - dev: true - /path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - dev: true + path-exists@3.0.0: {} - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} + path-exists@4.0.0: {} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} + path-is-absolute@1.0.1: {} - /path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - dev: false + path-key@2.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true + path-key@3.1.1: {} - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true + path-key@4.0.0: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-parse@1.0.7: {} - /path-starts-with@2.0.1: - resolution: {integrity: sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg==} - engines: {node: '>=8'} - dev: true + path-starts-with@2.0.1: {} - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + path-type@4.0.0: {} - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + pathval@1.1.1: {} - /pbkdf2@3.1.2: - resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} - engines: {node: '>=0.12'} + pbkdf2@3.1.2: dependencies: create-hash: 1.2.0 create-hmac: 1.1.7 @@ -5182,480 +6870,286 @@ packages: safe-buffer: 5.2.1 sha.js: 2.4.11 - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} + picomatch@2.3.1: {} - /pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - dev: true + pidtree@0.6.0: {} - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: false + pify@4.0.1: {} - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 - dev: false - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true + pluralize@8.0.0: {} - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - requiresBuild: true - dev: false + possible-typed-array-names@1.0.0: optional: true - /preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} - engines: {node: '>=10'} + preferred-pm@3.1.3: dependencies: find-up: 5.0.0 find-yarn-workspace-root2: 1.2.16 path-exists: 4.0.0 which-pm: 2.0.0 - dev: false - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true + prelude-ls@1.2.1: {} - /prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} + prettier-linter-helpers@1.0.0: dependencies: fast-diff: 1.2.0 - dev: true - /prettier-plugin-solidity@1.3.1(prettier@2.8.8): - resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} - engines: {node: '>=16'} - peerDependencies: - prettier: '>=2.3.0' + prettier-plugin-solidity@1.3.1(prettier@2.8.8): dependencies: '@solidity-parser/parser': 0.17.0 prettier: 2.8.8 semver: 7.6.2 solidity-comments-extractor: 0.0.8 - dev: true optional: true - /prettier-plugin-solidity@1.3.1(prettier@3.2.5): - resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} - engines: {node: '>=16'} - peerDependencies: - prettier: '>=2.3.0' + prettier-plugin-solidity@1.3.1(prettier@3.2.5): dependencies: '@solidity-parser/parser': 0.17.0 prettier: 3.2.5 semver: 7.6.2 solidity-comments-extractor: 0.0.8 - dev: true - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true + prettier@2.8.8: {} - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true + prettier@3.2.5: {} - /proper-lockfile@4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - requiresBuild: true + proper-lockfile@4.1.2: dependencies: graceful-fs: 4.2.10 retry: 0.12.0 signal-exit: 3.0.7 - dev: false optional: true - /proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - dev: true + proto-list@1.2.4: {} - /pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: false + pseudomap@1.0.2: {} - /pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - requiresBuild: true + pump@3.0.0: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - dev: true - /punycode@2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - dev: true + punycode@2.1.1: {} - /pure-rand@5.0.3: - resolution: {integrity: sha512-9N8x1h8dptBQpHyC7aZMS+iNOAm97WMGY0AFrguU1cpfW3I5jINkWe5BIY5md0ofy+1TCIELsVcm/GJXZSaPbw==} - dev: true + pure-rand@5.0.3: {} - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: false + quick-lru@4.0.1: {} - /quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} - dev: true + quick-lru@5.1.1: {} - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 - /raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} + raw-body@2.5.1: dependencies: bytes: 3.1.2 http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - dev: true - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true + rc@1.2.8: dependencies: deep-extend: 0.6.0 ini: 1.3.8 minimist: 1.2.8 strip-json-comments: 2.0.1 - dev: true - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 read-pkg: 5.2.0 type-fest: 0.8.1 - dev: false - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} + read-pkg@5.2.0: dependencies: '@types/normalize-package-data': 2.4.4 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 - dev: false - /read-yaml-file@1.1.0: - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} - engines: {node: '>=6'} + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.10 js-yaml: 3.14.1 pify: 4.0.1 strip-bom: 3.0.0 - dev: false - /readable-stream@3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} - engines: {node: '>= 6'} + readable-stream@3.6.0: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@3.6.0: dependencies: picomatch: 2.3.1 - dev: true - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} + redent@3.0.0: dependencies: indent-string: 4.0.0 strip-indent: 3.0.0 - dev: false - /reduce-flatten@2.0.0: - resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} - engines: {node: '>=6'} - dev: true + reduce-flatten@2.0.0: {} - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + regenerator-runtime@0.14.1: {} - /regexp.prototype.flags@1.5.1: - resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} - engines: {node: '>= 0.4'} + regexp.prototype.flags@1.5.1: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 set-function-name: 2.0.1 - dev: false - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - requiresBuild: true + regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-errors: 1.3.0 set-function-name: 2.0.1 - dev: false optional: true - /registry-auth-token@5.0.2: - resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} - engines: {node: '>=14'} + registry-auth-token@5.0.2: dependencies: '@pnpm/npm-conf': 2.2.2 - dev: true - /registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} + registry-url@6.0.1: dependencies: rc: 1.2.8 - dev: true - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} + require-directory@2.1.1: {} - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true + require-from-string@2.0.2: {} - /require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: false + require-main-filename@2.0.0: {} - /resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - dev: true + resolve-alpn@1.2.1: {} - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true + resolve-from@4.0.0: {} - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: false + resolve-from@5.0.0: {} - /resolve@1.17.0: - resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} + resolve@1.17.0: dependencies: path-parse: 1.0.7 - dev: true - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true + resolve@1.22.1: dependencies: is-core-module: 2.10.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: false - /responselike@2.0.1: - resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + responselike@2.0.1: dependencies: lowercase-keys: 2.0.0 - dev: true - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + restore-cursor@4.0.0: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - dev: true - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - requiresBuild: true - dev: false + retry@0.12.0: optional: true - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + reusify@1.0.4: {} - /rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - dev: true + rfdc@1.3.1: {} - /rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true + rimraf@2.7.1: dependencies: glob: 7.2.3 - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true + rimraf@3.0.2: dependencies: glob: 7.2.3 - dev: true - /ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + ripemd160@2.0.2: dependencies: hash-base: 3.1.0 inherits: 2.0.4 - /rlp@2.2.7: - resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} - hasBin: true + rlp@2.2.7: dependencies: bn.js: 5.2.1 - /run-parallel@1.1.9: - resolution: {integrity: sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==} + run-parallel@1.1.9: {} - /rust-verkle-wasm@0.0.1: - resolution: {integrity: sha512-BN6fiTsxcd2dCECz/cHtGTt9cdLJR925nh7iAuRcj8ymKw7OOaPmCneQZ7JePOJ/ia27TjEL91VdOi88Yf+mcA==} - dev: true + rust-verkle-wasm@0.0.1: {} - /rustbn-wasm@0.2.0: - resolution: {integrity: sha512-FThvYFNTqrEKGqXuseeg0zR7yROh/6U1617mCHF68OVqrN1tNKRN7Tdwy4WayPVsCmmK+eMxtIZX1qL6JxTkMg==} + rustbn-wasm@0.2.0: dependencies: '@scure/base': 1.1.1 - dev: true - /safe-array-concat@1.0.1: - resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} - engines: {node: '>=0.4'} + safe-array-concat@1.0.1: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 has-symbols: 1.0.3 isarray: 2.0.5 - dev: false - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - requiresBuild: true + safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 has-symbols: 1.0.3 isarray: 2.0.5 - dev: false optional: true - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true + safe-buffer@5.1.2: {} - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-buffer@5.2.1: {} - /safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + safe-regex-test@1.0.0: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-regex: 1.1.4 - dev: false - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - requiresBuild: true + safe-regex-test@1.0.3: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-regex: 1.1.4 - dev: false optional: true - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + safer-buffer@2.1.2: {} - /scrypt-js@3.0.1: - resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + scrypt-js@3.0.1: {} - /secp256k1@4.0.3: - resolution: {integrity: sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==} - engines: {node: '>=10.0.0'} - requiresBuild: true + secp256k1@4.0.3: dependencies: elliptic: 6.5.4 node-addon-api: 2.0.2 node-gyp-build: 4.5.0 - /semver@5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true + semver@5.7.1: {} - /semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - dev: true + semver@6.3.0: {} - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true + semver@7.6.2: {} - /sentence-case@2.1.1: - resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} + sentence-case@2.1.1: dependencies: no-case: 2.3.2 upper-case-first: 1.1.2 - dev: true - /serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + serialize-javascript@6.0.0: dependencies: randombytes: 2.1.0 - dev: true - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: false + set-blocking@2.0.0: {} - /set-function-length@1.1.1: - resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} - engines: {node: '>= 0.4'} + set-function-length@1.1.1: dependencies: define-data-property: 1.1.1 get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: false - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - requiresBuild: true + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 @@ -5663,114 +7157,68 @@ packages: get-intrinsic: 1.2.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 - dev: false optional: true - /set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} - engines: {node: '>= 0.4'} + set-function-name@2.0.1: dependencies: define-data-property: 1.1.1 functions-have-names: 1.2.3 has-property-descriptors: 1.0.0 - dev: false - /setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setimmediate@1.0.5: {} - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true + setprototypeof@1.2.0: {} - /sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true + sha.js@2.4.11: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - /shallowequal@1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - dev: true + shallowequal@1.1.0: {} - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 - dev: false - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: false + shebang-regex@1.0.0: {} - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true + shebang-regex@3.0.0: {} - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + side-channel@1.0.4: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 object-inspect: 1.13.1 - dev: false - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@3.0.7: {} - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true + signal-exit@4.1.0: {} - /slash@2.0.0: - resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} - engines: {node: '>=6'} - dev: false + slash@2.0.0: {} - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} + slash@3.0.0: {} - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + slice-ansi@4.0.0: dependencies: ansi-styles: 4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - dev: true - /slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} + slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 - dev: true - /slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} - engines: {node: '>=18'} + slice-ansi@7.1.0: dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 - dev: true - /smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true + smartwrap@2.0.2: dependencies: array.prototype.flat: 1.3.2 breakword: 1.0.6 @@ -5778,18 +7226,12 @@ packages: strip-ansi: 6.0.1 wcwidth: 1.0.1 yargs: 15.4.1 - dev: false - /snake-case@2.1.0: - resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} + snake-case@2.1.0: dependencies: no-case: 2.3.2 - dev: true - /solc@0.7.3(debug@4.3.4): - resolution: {integrity: sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==} - engines: {node: '>=8.0.0'} - hasBin: true + solc@0.7.3(debug@4.3.4): dependencies: command-exists: 1.2.9 commander: 3.0.2 @@ -5802,23 +7244,15 @@ packages: tmp: 0.0.33 transitivePeerDependencies: - debug - dev: true - /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5): - resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} - peerDependencies: - prettier: ^3.0.0 - prettier-plugin-solidity: ^1.0.0 + solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5): dependencies: '@prettier/sync': 0.3.0(prettier@3.2.5) prettier: 3.2.5 prettier-linter-helpers: 1.0.0 prettier-plugin-solidity: 1.3.1(prettier@3.2.5) - dev: true - /solhint@5.0.1: - resolution: {integrity: sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg==} - hasBin: true + solhint@5.0.1: dependencies: '@solidity-parser/parser': 0.18.0 ajv: 6.12.6 @@ -5840,113 +7274,45 @@ packages: text-table: 0.2.0 optionalDependencies: prettier: 2.8.8 - dev: true - /solidity-ast@0.4.56: - resolution: {integrity: sha512-HgmsA/Gfklm/M8GFbCX/J1qkVH0spXHgALCNZ8fA8x5X+MFdn/8CP2gr5OVyXjXw6RZTPC/Sxl2RUDQOXyNMeA==} - requiresBuild: true + solidity-ast@0.4.56: dependencies: array.prototype.findlast: 1.2.5 - dev: false optional: true - /solidity-comments-darwin-arm64@0.0.2: - resolution: {integrity: sha512-HidWkVLSh7v+Vu0CA7oI21GWP/ZY7ro8g8OmIxE8oTqyMwgMbE8F1yc58Sj682Hj199HCZsjmtn1BE4PCbLiGA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true + solidity-comments-darwin-arm64@0.0.2: optional: true - /solidity-comments-darwin-x64@0.0.2: - resolution: {integrity: sha512-Zjs0Ruz6faBTPT6fBecUt6qh4CdloT8Bwoc0+qxRoTn9UhYscmbPQkUgQEbS0FQPysYqVzzxJB4h1Ofbf4wwtA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true + solidity-comments-darwin-x64@0.0.2: optional: true - /solidity-comments-extractor@0.0.8: - resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} - dev: true + solidity-comments-extractor@0.0.8: {} - /solidity-comments-freebsd-x64@0.0.2: - resolution: {integrity: sha512-8Qe4mpjuAxFSwZJVk7B8gAoLCdbtS412bQzBwk63L8dmlHogvE39iT70aAk3RHUddAppT5RMBunlPUCFYJ3ZTw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true + solidity-comments-freebsd-x64@0.0.2: optional: true - /solidity-comments-linux-arm64-gnu@0.0.2: - resolution: {integrity: sha512-spkb0MZZnmrP+Wtq4UxP+nyPAVRe82idOjqndolcNR0S9Xvu4ebwq+LvF4HiUgjTDmeiqYiFZQ8T9KGdLSIoIg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + solidity-comments-linux-arm64-gnu@0.0.2: optional: true - /solidity-comments-linux-arm64-musl@0.0.2: - resolution: {integrity: sha512-guCDbHArcjE+JDXYkxx5RZzY1YF6OnAKCo+sTC5fstyW/KGKaQJNPyBNWuwYsQiaEHpvhW1ha537IvlGek8GqA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + solidity-comments-linux-arm64-musl@0.0.2: optional: true - /solidity-comments-linux-x64-gnu@0.0.2: - resolution: {integrity: sha512-zIqLehBK/g7tvrFmQljrfZXfkEeLt2v6wbe+uFu6kH/qAHZa7ybt8Vc0wYcmjo2U0PeBm15d79ee3AkwbIjFdQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + solidity-comments-linux-x64-gnu@0.0.2: optional: true - /solidity-comments-linux-x64-musl@0.0.2: - resolution: {integrity: sha512-R9FeDloVlFGTaVkOlELDVC7+1Tjx5WBPI5L8r0AGOPHK3+jOcRh6sKYpI+VskSPDc3vOO46INkpDgUXrKydlIw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + solidity-comments-linux-x64-musl@0.0.2: optional: true - /solidity-comments-win32-arm64-msvc@0.0.2: - resolution: {integrity: sha512-QnWJoCQcJj+rnutULOihN9bixOtYWDdF5Rfz9fpHejL1BtNjdLW1om55XNVHGAHPqBxV4aeQQ6OirKnp9zKsug==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true + solidity-comments-win32-arm64-msvc@0.0.2: optional: true - /solidity-comments-win32-ia32-msvc@0.0.2: - resolution: {integrity: sha512-vUg4nADtm/NcOtlIymG23NWJUSuMsvX15nU7ynhGBsdKtt8xhdP3C/zA6vjDk8Jg+FXGQL6IHVQ++g/7rSQi0w==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true + solidity-comments-win32-ia32-msvc@0.0.2: optional: true - /solidity-comments-win32-x64-msvc@0.0.2: - resolution: {integrity: sha512-36j+KUF4V/y0t3qatHm/LF5sCUCBx2UndxE1kq5bOzh/s+nQgatuyB+Pd5BfuPQHdWu2KaExYe20FlAa6NL7+Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true + solidity-comments-win32-x64-msvc@0.0.2: optional: true - /solidity-comments@0.0.2: - resolution: {integrity: sha512-G+aK6qtyUfkn1guS8uzqUeua1dURwPlcOjoTYW/TwmXAcE7z/1+oGCfZUdMSe4ZMKklNbVZNiG5ibnF8gkkFfw==} - engines: {node: '>= 12'} + solidity-comments@0.0.2: optionalDependencies: solidity-comments-darwin-arm64: 0.0.2 solidity-comments-darwin-x64: 0.0.2 @@ -5958,355 +7324,211 @@ packages: solidity-comments-win32-arm64-msvc: 0.0.2 solidity-comments-win32-ia32-msvc: 0.0.2 solidity-comments-win32-x64-msvc: 0.0.2 - dev: true - /sort-any@2.0.0: - resolution: {integrity: sha512-T9JoiDewQEmWcnmPn/s9h/PH9t3d/LSWi0RgVmXSuDYeZXTZOZ1/wrK2PHaptuR1VXe3clLLt0pD6sgVOwjNEA==} + sort-any@2.0.0: dependencies: lodash: 4.17.21 - dev: true - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map@0.6.1: {} - /spawndamnit@2.0.0: - resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + spawndamnit@2.0.0: dependencies: cross-spawn: 5.1.0 signal-exit: 3.0.7 - dev: false - /spdx-correct@3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + spdx-correct@3.1.1: dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.12 - dev: false - /spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: false + spdx-exceptions@2.3.0: {} - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.12 - dev: false - /spdx-license-ids@3.0.12: - resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} - dev: false + spdx-license-ids@3.0.12: {} - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: false + sprintf-js@1.0.3: {} - /stacktrace-parser@0.1.10: - resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} - engines: {node: '>=6'} + stacktrace-parser@0.1.10: dependencies: type-fest: 0.7.1 - dev: true - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true + statuses@2.0.1: {} - /stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + stream-transform@2.1.3: dependencies: mixme: 0.5.10 - dev: false - /string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - dev: true + string-argv@0.3.2: {} - /string-format@2.0.0: - resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} - dev: true + string-format@2.0.0: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - /string-width@7.1.0: - resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} - engines: {node: '>=18'} + string-width@7.1.0: dependencies: emoji-regex: 10.3.0 get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 - dev: true - /string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} - engines: {node: '>= 0.4'} + string.prototype.trim@1.2.8: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 - dev: false - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - requiresBuild: true + string.prototype.trim@1.2.9: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 es-object-atoms: 1.0.0 - dev: false optional: true - /string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + string.prototype.trimend@1.0.7: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 - dev: false - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - requiresBuild: true + string.prototype.trimend@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 - dev: false optional: true - /string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string.prototype.trimstart@1.0.7: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 - dev: false - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - requiresBuild: true + string.prototype.trimstart@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 - dev: false optional: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + strip-ansi@7.1.0: dependencies: ansi-regex: 6.0.1 - dev: true - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: false + strip-bom@3.0.0: {} - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true + strip-final-newline@3.0.0: {} - /strip-hex-prefix@1.0.0: - resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=} - engines: {node: '>=6.5.0', npm: '>=3'} + strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed: 1.0.0 - dev: true - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 - dev: false - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - dev: true + strip-json-comments@2.0.1: {} - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true + strip-json-comments@3.1.1: {} - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + supports-color@8.1.1: dependencies: has-flag: 4.0.0 - dev: true - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: false + supports-preserve-symlinks-flag@1.0.0: {} - /swap-case@1.1.2: - resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} + swap-case@1.1.2: dependencies: lower-case: 1.1.4 upper-case: 1.1.3 - dev: true - /synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} - engines: {node: ^14.18.0 || >=16.0.0} + synckit@0.8.8: dependencies: '@pkgr/core': 0.1.1 tslib: 2.6.2 - dev: true - /table-layout@1.0.2: - resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} - engines: {node: '>=8.0.0'} + table-layout@1.0.2: dependencies: array-back: 4.0.2 deep-extend: 0.6.0 typical: 5.2.0 wordwrapjs: 4.0.1 - dev: true - /table@6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} + table@6.8.1: dependencies: ajv: 8.11.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /term-size@2.2.1: - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} - engines: {node: '>=8'} - dev: false + term-size@2.2.1: {} - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true + text-table@0.2.0: {} - /title-case@2.1.1: - resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} + title-case@2.1.1: dependencies: no-case: 2.3.2 upper-case: 1.1.3 - dev: true - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true + toidentifier@1.0.1: {} - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false + tr46@0.0.3: {} - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: false + trim-newlines@3.0.1: {} - /ts-api-utils@1.3.0(typescript@5.4.5): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' + ts-api-utils@1.3.0(typescript@5.4.5): dependencies: typescript: 5.4.5 - dev: true - /ts-command-line-args@2.5.1: - resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} - hasBin: true + ts-command-line-args@2.5.1: dependencies: chalk: 4.1.2 command-line-args: 5.2.1 command-line-usage: 6.1.3 string-format: 2.0.0 - dev: true - /ts-essentials@7.0.3(typescript@5.4.5): - resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} - peerDependencies: - typescript: '>=3.7.0' + ts-essentials@7.0.3(typescript@5.4.5): dependencies: typescript: 5.4.5 - dev: true - /ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 @@ -6323,24 +7545,14 @@ packages: typescript: 5.4.5 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true + tslib@1.14.1: {} - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true + tslib@2.6.2: {} - /tsort@0.0.1: - resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - dev: true + tsort@0.0.1: {} - /tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true + tty-table@4.2.3: dependencies: chalk: 4.1.2 csv: 5.5.3 @@ -6349,65 +7561,33 @@ packages: strip-ansi: 6.0.1 wcwidth: 1.0.1 yargs: 17.7.2 - dev: false - /tweetnacl-util@0.15.1: - resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} - dev: true + tweetnacl-util@0.15.1: {} - /tweetnacl@1.0.3: - resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} - dev: true + tweetnacl@1.0.3: {} - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - dev: true - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} + type-detect@4.0.8: {} - /type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - dev: false + type-fest@0.13.1: {} - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true + type-fest@0.20.2: {} - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true + type-fest@0.21.3: {} - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: false + type-fest@0.6.0: {} - /type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - dev: true + type-fest@0.7.1: {} - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: false + type-fest@0.8.1: {} - /typechain@8.3.2(typescript@5.4.5): - resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} - hasBin: true - peerDependencies: - typescript: '>=4.3.0' + typechain@8.3.2(typescript@5.4.5): dependencies: '@types/prettier': 2.7.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) fs-extra: 7.0.1 glob: 7.1.7 js-sha3: 0.8.0 @@ -6419,66 +7599,45 @@ packages: typescript: 5.4.5 transitivePeerDependencies: - supports-color - dev: true - /typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} - engines: {node: '>= 0.4'} + typed-array-buffer@1.0.0: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-typed-array: 1.1.12 - dev: false - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - requiresBuild: true + typed-array-buffer@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-typed-array: 1.1.13 - dev: false optional: true - /typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} - engines: {node: '>= 0.4'} + typed-array-byte-length@1.0.0: dependencies: call-bind: 1.0.5 for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 - dev: false - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - requiresBuild: true + typed-array-byte-length@1.0.1: 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 - dev: false optional: true - /typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} - engines: {node: '>= 0.4'} + typed-array-byte-offset@1.0.0: dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.5 for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 - dev: false - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - requiresBuild: true + typed-array-byte-offset@1.0.2: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -6486,20 +7645,15 @@ packages: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - dev: false optional: true - /typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + typed-array-length@1.0.4: dependencies: call-bind: 1.0.5 for-each: 0.3.3 is-typed-array: 1.1.12 - dev: false - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} + typed-array-length@1.0.6: dependencies: call-bind: 1.0.7 for-each: 0.3.3 @@ -6507,105 +7661,61 @@ packages: has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - dev: false optional: true - /typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} - engines: {node: '>=14.17'} - hasBin: true - dev: true + typescript@5.4.5: {} - /typical@4.0.0: - resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} - engines: {node: '>=8'} - dev: true + typical@4.0.0: {} - /typical@5.2.0: - resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} - engines: {node: '>=8'} - dev: true + typical@5.2.0: {} - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.5 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: false - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@5.26.5: {} - /undici@5.28.4: - resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} - engines: {node: '>=14.0'} + undici@5.28.4: dependencies: '@fastify/busboy': 2.1.1 - dev: true - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} + universalify@0.1.2: {} - /universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} - engines: {node: '>= 10.0.0'} + universalify@2.0.0: {} - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true + unpipe@1.0.0: {} - /upper-case-first@1.1.2: - resolution: {integrity: sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ==} + upper-case-first@1.1.2: dependencies: upper-case: 1.1.3 - dev: true - /upper-case@1.1.3: - resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} - dev: true + upper-case@1.1.3: {} - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uri-js@4.4.1: dependencies: punycode: 2.1.1 - dev: true - /utf8@3.0.0: - resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - dev: true + utf8@3.0.0: {} - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + util-deprecate@1.0.2: {} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true + uuid@8.3.2: {} - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true + v8-compile-cache-lib@3.0.1: {} - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.1.1 spdx-expression-parse: 3.0.1 - dev: false - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + wcwidth@1.0.1: dependencies: defaults: 1.0.4 - dev: false - /web3-utils@1.7.4: - resolution: {integrity: sha512-acBdm6Evd0TEZRnChM/MCvGsMwYKmSh7OaUfNf5OKG0CIeGWD/6gqLOWIwmwSnre/2WrA1nKGId5uW2e5EfluA==} - engines: {node: '>=8.0.0'} + web3-utils@1.7.4: dependencies: bn.js: 5.2.1 ethereum-bloom-filters: 1.0.10 @@ -6614,206 +7724,116 @@ packages: number-to-bn: 1.7.0 randombytes: 2.1.0 utf8: 3.0.0 - dev: true - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false + webidl-conversions@3.0.1: {} - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: false - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 is-boolean-object: 1.1.2 is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.3 - dev: false - /which-module@2.0.0: - resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} - dev: false + which-module@2.0.0: {} - /which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} + which-pm@2.0.0: dependencies: load-yaml-file: 0.2.0 path-exists: 4.0.0 - dev: false - /which-typed-array@1.1.13: - resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} - engines: {node: '>= 0.4'} + which-typed-array@1.1.13: dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.5 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 - dev: false - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - requiresBuild: true + which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.2 - dev: false optional: true - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true + which@1.3.1: dependencies: isexe: 2.0.0 - dev: false - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: true - /widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} + widest-line@3.1.0: dependencies: string-width: 4.2.3 - dev: true - /wordwrapjs@4.0.1: - resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} - engines: {node: '>=8.0.0'} + wordwrapjs@4.0.1: dependencies: reduce-flatten: 2.0.0 typical: 5.2.0 - dev: true - /workerpool@6.2.1: - resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} - dev: true + workerpool@6.2.1: {} - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: false - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - /wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 string-width: 7.1.0 strip-ansi: 7.1.0 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + wrappy@1.0.2: {} - /ws@7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true + ws@7.4.6: {} - /ws@7.5.9: - resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true + ws@7.5.9: {} - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: false + y18n@4.0.3: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} + y18n@5.0.8: {} - /yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: false + yallist@2.1.2: {} - /yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - dev: false + yaml@1.10.2: {} - /yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - dev: true + yaml@2.3.4: {} - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 decamelize: 1.2.0 - dev: false - /yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - dev: true + yargs-parser@20.2.4: {} - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false + yargs-parser@21.1.1: {} - /yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} + yargs-unparser@2.0.0: dependencies: camelcase: 6.3.0 decamelize: 4.0.0 flat: 5.0.2 is-plain-obj: 2.1.0 - dev: true - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} + yargs@15.4.1: dependencies: cliui: 6.0.0 decamelize: 1.2.0 @@ -6826,11 +7846,8 @@ packages: which-module: 2.0.0 y18n: 4.0.3 yargs-parser: 18.1.3 - dev: false - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} + yargs@16.2.0: dependencies: cliui: 7.0.4 escalade: 3.1.1 @@ -6839,11 +7856,8 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 20.2.4 - dev: true - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@17.7.2: dependencies: cliui: 8.0.1 escalade: 3.1.1 @@ -6852,19 +7866,7 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: false - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + yn@3.1.1: {} - github.com/smartcontractkit/chainlink-solhint-rules/1b4c0c2663fcd983589d4f33a2e73908624ed43c: - resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c} - name: '@chainlink/solhint-plugin-chainlink-solidity' - version: 1.2.0 - dev: true + yocto-queue@0.1.0: {} diff --git a/contracts/remappings.txt b/contracts/remappings.txt index a314323752..ec64b1b211 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -1,5 +1,4 @@ -ds-test/=foundry-lib/forge-std/lib/ds-test/src/ -forge-std/=foundry-lib/forge-std/src/ +forge-std/=src/v0.8/vendor/forge-std/src/ @openzeppelin/=node_modules/@openzeppelin/ @arbitrum/=node_modules/@arbitrum/ diff --git a/contracts/scripts/generate-automation-master-interface-v2_3.ts b/contracts/scripts/generate-automation-master-interface-v2_3.ts index cb566d744b..1e2d713cab 100644 --- a/contracts/scripts/generate-automation-master-interface-v2_3.ts +++ b/contracts/scripts/generate-automation-master-interface-v2_3.ts @@ -10,7 +10,7 @@ import { utils } from 'ethers' import fs from 'fs' import { exec } from 'child_process' -const dest = 'src/v0.8/automation/dev/interfaces/v2_3' +const dest = 'src/v0.8/automation/interfaces/v2_3' const srcDest = `${dest}/IAutomationRegistryMaster2_3.sol` const tmpDest = `${dest}/tmp.txt` diff --git a/contracts/scripts/native_solc_compile_all_automation b/contracts/scripts/native_solc_compile_all_automation index 60b57e71ce..f144e4f7dc 100755 --- a/contracts/scripts/native_solc_compile_all_automation +++ b/contracts/scripts/native_solc_compile_all_automation @@ -99,10 +99,13 @@ compileContract automation/interfaces/IChainModule.sol compileContract automation/interfaces/IAutomationV21PlusCommon.sol compileContract automation/AutomationCompatibleUtils.sol -compileContract automation/dev/v2_3/AutomationRegistrar2_3.sol -compileContract automation/dev/v2_3/AutomationRegistry2_3.sol -compileContract automation/dev/v2_3/AutomationRegistryLogicA2_3.sol -compileContract automation/dev/v2_3/AutomationRegistryLogicB2_3.sol -compileContract automation/dev/v2_3/AutomationRegistryLogicC2_3.sol -compileContract automation/dev/v2_3/AutomationUtils2_3.sol -compileContract automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +compileContract automation/v2_3/AutomationRegistrar2_3.sol +compileContract automation/v2_3/AutomationRegistry2_3.sol +compileContract automation/v2_3/AutomationRegistryLogicA2_3.sol +compileContract automation/v2_3/AutomationRegistryLogicB2_3.sol +compileContract automation/v2_3/AutomationRegistryLogicC2_3.sol +compileContract automation/v2_3/AutomationUtils2_3.sol +compileContract automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol + +compileContract automation/testhelpers/MockETHUSDAggregator.sol +compileContract automation/test/v2_3/WETH9.sol diff --git a/contracts/scripts/native_solc_compile_all_keystone b/contracts/scripts/native_solc_compile_all_keystone index 1530b307db..0516b2aedb 100755 --- a/contracts/scripts/native_solc_compile_all_keystone +++ b/contracts/scripts/native_solc_compile_all_keystone @@ -6,7 +6,7 @@ echo " ┌─────────────────────── echo " │ Compiling Keystone contracts... │" echo " └──────────────────────────────────────────────┘" -SOLC_VERSION="0.8.19" +SOLC_VERSION="0.8.24" OPTIMIZE_RUNS=1000000 @@ -25,9 +25,10 @@ compileContract () { solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ + --evm-version paris \ "$ROOT"/contracts/src/v0.8/"$1" } -compileContract keystone/CapabilityRegistry.sol +compileContract keystone/CapabilitiesRegistry.sol compileContract keystone/KeystoneForwarder.sol compileContract keystone/OCR3Capability.sol diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol similarity index 75% rename from contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol rename to contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol index d3591a924f..7477c02f12 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ b/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -1,4 +1,4 @@ -// abi-checksum: 0x663e54f1d800f7d488622966574e41eb76fdeb6c5b7160541dc6173eb53e4577 +// abi-checksum: 0xacb9d0daec3e3bed110c8cf95bdbe7280a21ce61519d4cd496f802884bf05524 // SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! pragma solidity ^0.8.4; @@ -237,6 +237,7 @@ interface IAutomationRegistryMaster2_3 { function getBillingOverrides( uint256 upkeepID ) external view returns (AutomationRegistryBase2_3.BillingOverrides memory); + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool); function getBillingToken(uint256 upkeepID) external view returns (address); function getBillingTokenConfig(address token) external view returns (AutomationRegistryBase2_3.BillingConfig memory); function getBillingTokens() external view returns (address[] memory); @@ -430,5 +431,5 @@ interface IAutomationV21PlusCommon { // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: /* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint96","name":"gasChargeInBillingToken","type":"uint96"},{"internalType":"uint96","name":"premiumInBillingToken","type":"uint96"},{"internalType":"uint96","name":"gasReimbursementInJuels","type":"uint96"},{"internalType":"uint96","name":"premiumInJuels","type":"uint96"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"uint96","name":"linkUSD","type":"uint96"},{"internalType":"uint96","name":"nativeUSD","type":"uint96"},{"internalType":"uint96","name":"billingUSD","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.PaymentReceipt","name":"receipt","type":"tuple"}],"name":"UpkeepCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint96","name":"gasChargeInBillingToken","type":"uint96"},{"internalType":"uint96","name":"premiumInBillingToken","type":"uint96"},{"internalType":"uint96","name":"gasReimbursementInJuels","type":"uint96"},{"internalType":"uint96","name":"premiumInJuels","type":"uint96"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"uint96","name":"linkUSD","type":"uint96"},{"internalType":"uint96","name":"nativeUSD","type":"uint96"},{"internalType":"uint96","name":"billingUSD","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.PaymentReceipt","name":"receipt","type":"tuple"}],"name":"UpkeepCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverridesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] */ diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol b/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol similarity index 55% rename from contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol rename to contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol index dd37103302..fdbd7ddad6 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol +++ b/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IERC20Metadata as IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; interface IWrappedNative is IERC20 { function deposit() external payable; diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol b/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol similarity index 96% rename from contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol rename to contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol index 2b55651dbe..171e4e3718 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {AutomationRegistrar2_3} from "../v2_3/AutomationRegistrar2_3.sol"; +import {IAutomationRegistryMaster2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {AutomationRegistryBase2_3 as AutoBase} from "../v2_3/AutomationRegistryBase2_3.sol"; -import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; +import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; -// forge test --match-path src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol +// forge test --match-path src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol contract SetUp is BaseTest { IAutomationRegistryMaster2_3 internal registry; diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol similarity index 99% rename from contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol rename to contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol index 915972d703..dbc0c203c0 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol @@ -3,14 +3,14 @@ pragma solidity 0.8.19; import {Vm} from "forge-std/Test.sol"; import {BaseTest} from "./BaseTest.t.sol"; -import {AutomationRegistryBase2_3 as AutoBase} from "../v2_3/AutomationRegistryBase2_3.sol"; -import {AutomationRegistrar2_3 as Registrar} from "../v2_3/AutomationRegistrar2_3.sol"; -import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; +import {AutomationRegistrar2_3 as Registrar} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; -// forge test --match-path src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +// forge test --match-path src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol enum Trigger { CONDITION, diff --git a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol b/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol similarity index 96% rename from contracts/src/v0.8/automation/dev/test/BaseTest.t.sol rename to contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol index bba195b83e..9016f52c55 100644 --- a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol @@ -8,18 +8,18 @@ import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/ import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; -import {UpkeepTranscoder5_0 as Transcoder} from "../v2_3/UpkeepTranscoder5_0.sol"; -import {AutomationRegistry2_3} from "../v2_3/AutomationRegistry2_3.sol"; -import {AutomationRegistryBase2_3 as AutoBase} from "../v2_3/AutomationRegistryBase2_3.sol"; -import {AutomationRegistryLogicA2_3} from "../v2_3/AutomationRegistryLogicA2_3.sol"; -import {AutomationRegistryLogicB2_3} from "../v2_3/AutomationRegistryLogicB2_3.sol"; -import {AutomationRegistryLogicC2_3} from "../v2_3/AutomationRegistryLogicC2_3.sol"; -import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {AutomationRegistrar2_3} from "../v2_3/AutomationRegistrar2_3.sol"; +import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; +import {AutomationRegistry2_3} from "../../v2_3/AutomationRegistry2_3.sol"; +import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; +import {AutomationRegistryLogicA2_3} from "../../v2_3/AutomationRegistryLogicA2_3.sol"; +import {AutomationRegistryLogicB2_3} from "../../v2_3/AutomationRegistryLogicB2_3.sol"; +import {AutomationRegistryLogicC2_3} from "../../v2_3/AutomationRegistryLogicC2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; -import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; import {WETH9} from "./WETH9.sol"; /** diff --git a/contracts/src/v0.8/automation/dev/test/WETH9.sol b/contracts/src/v0.8/automation/test/v2_3/WETH9.sol similarity index 100% rename from contracts/src/v0.8/automation/dev/test/WETH9.sol rename to contracts/src/v0.8/automation/test/v2_3/WETH9.sol diff --git a/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol b/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol new file mode 100644 index 0000000000..10f6732c99 --- /dev/null +++ b/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../../shared/interfaces/AggregatorV3Interface.sol"; + +contract MockETHUSDAggregator is AggregatorV3Interface { + int256 public answer; + uint256 private blockTimestampDeduction = 0; + + constructor(int256 _answer) { + answer = _answer; + } + + function decimals() external pure override returns (uint8) { + return 8; + } + + function description() external pure override returns (string memory) { + return "MockETHUSDAggregator"; + } + + function version() external pure override returns (uint256) { + return 1; + } + + function getRoundData( + uint80 /*_roundId*/ + ) + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); + } + + function latestRoundData() + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); + } + + function getDeductedBlockTimestamp() internal view returns (uint256) { + return block.timestamp - blockTimestampDeduction; + } + + function setBlockTimestampDeduction(uint256 _blockTimestampDeduction) external { + blockTimestampDeduction = _blockTimestampDeduction; + } +} diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol similarity index 95% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol index 4476ac690a..2effb8d4d2 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; -import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @notice Contract to accept requests for upkeep registrations @@ -131,7 +131,8 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC bytes triggerConfig, bytes offchainConfig, bytes checkData, - uint96 amount + uint96 amount, + IERC20 billingToken ); event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); @@ -372,7 +373,8 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC params.triggerConfig, params.offchainConfig, params.checkData, - params.amount + params.amount, + params.billingToken ); uint256 upkeepId; diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol similarity index 97% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol index ba19fa2d55..6113cbf9fd 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; import {AutomationRegistryLogicA2_3} from "./AutomationRegistryLogicA2_3.sol"; import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; -import {Chainable} from "../../Chainable.sol"; -import {OCR2Abstract} from "../../../shared/ocr2/OCR2Abstract.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {Chainable} from "../Chainable.sol"; +import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; /** * @notice Registry for adding work for Chainlink nodes to perform on client diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol similarity index 97% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol index 5e979b9e3f..fa8f06ffc0 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {StreamsLookupCompatibleInterface} from "../../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ILogAutomation, Log} from "../../interfaces/ILogAutomation.sol"; -import {IAutomationForwarder} from "../../interfaces/IAutomationForwarder.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {KeeperCompatibleInterface} from "../../interfaces/KeeperCompatibleInterface.sol"; -import {IChainModule} from "../../interfaces/IChainModule.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; /** diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol similarity index 90% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol index 6cf63a8188..1ef399176b 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; import {AutomationRegistryLogicB2_3} from "./AutomationRegistryLogicB2_3.sol"; -import {Chainable} from "../../Chainable.sol"; -import {AutomationForwarder} from "../../AutomationForwarder.sol"; -import {IAutomationForwarder} from "../../interfaces/IAutomationForwarder.sol"; -import {UpkeepTranscoderInterfaceV2} from "../../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {MigratableKeeperRegistryInterfaceV2} from "../../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol"; +import {Chainable} from "../Chainable.sol"; +import {AutomationForwarder} from "../AutomationForwarder.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; /** * @notice Logic contract, works in tandem with AutomationRegistry as a proxy @@ -157,13 +157,14 @@ contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable, IE } /** - * @notice migrates upkeeps from one registry to another + * @notice migrates upkeeps from one registry to another. * @param ids the upkeepIDs to migrate * @param destination the destination registry address * @dev a transcoder must be set in order to enable migration * @dev migration permissions must be set on *both* sending and receiving registries * @dev only an upkeep admin can migrate their upkeeps * @dev this function is most gas-efficient if upkeepIDs are sorted by billing token + * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not migrated in this function */ function migrateUpkeeps(uint256[] calldata ids, address destination) external { if ( @@ -246,6 +247,7 @@ contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable, IE * @notice received upkeeps migrated from another registry * @param encodedUpkeeps the raw upkeep data to import * @dev this function is never called directly, it is only called by another registry's migrate function + * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not handled in this function */ function receiveUpkeeps(bytes calldata encodedUpkeeps) external { if ( diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol similarity index 96% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol index 29f253f8ce..d85484812f 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.19; import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; -import {Chainable} from "../../Chainable.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {Chainable} from "../Chainable.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { using Address for address; diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol similarity index 96% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol index 248cfcde94..8fc944829f 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol @@ -2,12 +2,12 @@ pragma solidity 0.8.19; import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {IAutomationForwarder} from "../../interfaces/IAutomationForwarder.sol"; -import {IChainModule} from "../../interfaces/IChainModule.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IAutomationV21PlusCommon} from "../../interfaces/IAutomationV21PlusCommon.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { using Address for address; @@ -286,6 +286,10 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { return s_billingConfigs[token]; } + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool) { + return s_upkeep[upkeepID].overridesEnabled; + } + function getPayoutMode() external view returns (PayoutMode) { return s_payoutMode; } diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationUtils2_3.sol b/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol similarity index 100% rename from contracts/src/v0.8/automation/dev/v2_3/AutomationUtils2_3.sol rename to contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol diff --git a/contracts/src/v0.8/automation/dev/v2_3/LICENSE b/contracts/src/v0.8/automation/v2_3/LICENSE similarity index 100% rename from contracts/src/v0.8/automation/dev/v2_3/LICENSE rename to contracts/src/v0.8/automation/v2_3/LICENSE diff --git a/contracts/src/v0.8/automation/dev/v2_3/UpkeepTranscoder5_0.sol b/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol similarity index 88% rename from contracts/src/v0.8/automation/dev/v2_3/UpkeepTranscoder5_0.sol rename to contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol index 6f3d556755..32530c7125 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/UpkeepTranscoder5_0.sol +++ b/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.19; -import {UpkeepTranscoderInterfaceV2} from "../../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; enum RegistryVersion { V12, diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol similarity index 80% rename from contracts/src/v0.8/keystone/CapabilityRegistry.sol rename to contracts/src/v0.8/keystone/CapabilitiesRegistry.sol index c2462bfecf..56df507867 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity 0.8.24; import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; @@ -7,7 +7,7 @@ import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfac import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; -/// @notice CapabilityRegistry is used to manage Nodes (including their links to Node +/// @notice CapabilitiesRegistry is used to manage Nodes (including their links to Node /// Operators), Capabilities, and DONs (Decentralized Oracle Networks) which are /// sets of nodes that support those Capabilities. /// @dev The contract currently stores the entire state of Node Operators, Nodes, @@ -15,7 +15,7 @@ import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.so /// if an upgrade is ever required. The team acknowledges this and is fine /// reconfiguring the upgraded contract in the future so as to not add extra /// complexity to this current version. -contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { +contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { // Add the library methods using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.UintSet; @@ -31,17 +31,39 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { string name; } + struct NodeParams { + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The signer address for application-layer message verification. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. + /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is + /// used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice The list of hashed capability IDs supported by the node + bytes32[] hashedCapabilityIds; + } + struct NodeInfo { /// @notice The id of the node operator that manages this node uint32 nodeOperatorId; + /// @notice The number of times the node's configuration has been updated + uint32 configCount; + /// @notice The ID of the Workflow DON that the node belongs to. A node can + /// only belong to one DON that accepts Workflows. + uint32 workflowDONId; /// @notice The signer address for application-layer message verification. bytes32 signer; /// @notice This is an Ed25519 public key that is used to identify a node. - /// This key is guaranteed to be unique in the CapabilityRegistry. It is + /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is /// used to identify a node in the the P2P network. bytes32 p2pId; /// @notice The list of hashed capability IDs supported by the node bytes32[] hashedCapabilityIds; + /// @notice The list of capabilities DON Ids supported by the node. A node + /// can belong to multiple capabilities DONs. This list does not include a + /// Workflow DON id if the node belongs to one. + uint256[] capabilitiesDONIds; } struct Node { @@ -50,8 +72,11 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { uint32 nodeOperatorId; /// @notice The number of times the node's configuration has been updated uint32 configCount; + /// @notice The ID of the Workflow DON that the node belongs to. A node can + /// only belong to one DON that accepts Workflows. + uint32 workflowDONId; /// @notice The signer address for application-layer message verification. - /// @dev This key is guaranteed to be unique in the CapabilityRegistry + /// @dev This key is guaranteed to be unique in the CapabilitiesRegistry /// as a signer address can only belong to one node. /// @dev This should be the ABI encoded version of the node's address. /// I.e 0x0000address. The Capability Registry does not store it as an address so that @@ -59,7 +84,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// in the future. bytes32 signer; /// @notice This is an Ed25519 public key that is used to identify a node. - /// This key is guaranteed to be unique in the CapabilityRegistry. It is + /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is /// used to identify a node in the the P2P network. bytes32 p2pId; /// @notice The node's supported capabilities @@ -67,8 +92,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// new capabilities by incrementing the configCount and creating a /// new set of supported capability IDs mapping(uint32 configCount => EnumerableSet.Bytes32Set capabilityId) supportedHashedCapabilityIds; - /// @notice The list of DON Ids supported by the node. - EnumerableSet.UintSet supportedDONIds; + /// @notice The list of capabilities DON Ids supported by the node. A node + /// can belong to multiple capabilities DONs. This list does not include a + /// Workflow DON id if the node belongs to one. + EnumerableSet.UintSet capabilitiesDONIds; } /// @notice CapabilityResponseType indicates whether remote response requires @@ -101,8 +128,41 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" /// labelledName = "data-streams-reports:chain:ethereum" + string labelledName; + /// @notice Semver, e.g., "1.2.3" + /// @dev must be valid Semver + max 32 characters. + string version; + /// @notice CapabilityType indicates the type of capability which determines + /// where the capability can be used in a Workflow Spec. + CapabilityType capabilityType; + /// @notice CapabilityResponseType indicates whether remote response requires + // aggregation or is an already aggregated report. There are multiple + // possible ways to aggregate. + CapabilityResponseType responseType; + /// @notice An address to the capability configuration contract. Having this defined + // on a capability enforces consistent configuration across DON instances + // serving the same capability. Configuration contract MUST implement + // CapabilityConfigurationContractInterface. + // + /// @dev The main use cases are: + // 1) Sharing capability configuration across DON instances + // 2) Inspect and modify on-chain configuration without off-chain + // capability code. + // + // It is not recommended to store configuration which requires knowledge of + // the DON membership. + address configurationContract; + } + + struct CapabilityInfo { + /// @notice A hashed ID created by the `getHashedCapabilityId` function. + bytes32 hashedId; + /// @notice The partially qualified ID for the capability. + /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} + // Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` portion of the ID. /// - /// validation regex: ^[a-z0-9_\-:]{1,32}$ + /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" + /// labelledName = "data-streams-reports:chain:ethereum" string labelledName; /// @notice Semver, e.g., "1.2.3" /// @dev must be valid Semver + max 32 characters. @@ -127,6 +187,8 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { // It is not recommended to store configuration which requires knowledge of // the DON membership. address configurationContract; + /// @notice True if the capability is deprecated + bool isDeprecated; } /// @notice CapabilityConfiguration is a struct that holds the capability configuration @@ -159,11 +221,13 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice The f value for the DON. This is the number of faulty nodes /// that the DON can tolerate. This can be different from the f value of /// the OCR instances that capabilities spawn. - uint32 f; + uint8 f; /// @notice True if the DON is public. A public DON means that it accepts /// external capability requests bool isPublic; - /// @notice True if the DON accepts Workflows. + /// @notice True if the DON accepts Workflows. A DON that accepts Workflows + /// is called Workflow DON and it can process Workflow Specs. A Workflow + /// DON also support one or more capabilities as well. bool acceptsWorkflows; /// @notice Mapping of config counts to configurations mapping(uint32 configCount => DONCapabilityConfig donConfig) config; @@ -177,7 +241,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice The f value for the DON. This is the number of faulty nodes /// that the DON can tolerate. This can be different from the f value of /// the OCR instances that capabilities spawn. - uint32 f; + uint8 f; /// @notice True if the DON is public. A public DON means that it accepts /// external capability requests bool isPublic; @@ -196,7 +260,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { uint32 configCount; bool isPublic; bool acceptsWorkflows; - uint32 f; + uint8 f; } /// @notice This error is thrown when a caller is not allowed @@ -265,7 +329,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// fault tolerance value. /// @param f The proposed fault tolerance value /// @param nodeCount The proposed number of nodes in the DON - error InvalidFaultTolerance(uint32 f, uint256 nodeCount); + error InvalidFaultTolerance(uint8 f, uint256 nodeCount); /// @notice This error is thrown when a capability with the provided hashed ID is /// not found. @@ -287,9 +351,24 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { error NodeOperatorDoesNotExist(uint32 nodeOperatorId); /// @notice This error is thrown when trying to remove a node that is still - /// part of a DON + /// part of a capabitlities DON + /// @param donId The Id of the DON the node belongs to /// @param nodeP2PId The P2P Id of the node being removed - error NodePartOfDON(bytes32 nodeP2PId); + error NodePartOfCapabilitiesDON(uint32 donId, bytes32 nodeP2PId); + + /// @notice This error is thrown when attempting to add a node to a second + /// Workflow DON or when trying to remove a node that belongs to a Workflow + /// DON + /// @param donId The Id of the DON the node belongs to + /// @param nodeP2PId The P2P Id of the node + error NodePartOfWorkflowDON(uint32 donId, bytes32 nodeP2PId); + + /// @notice This error is thrown when removing a capability from the node + /// when that capability is still required by one of the DONs the node + /// belongs to. + /// @param hashedCapabilityId The hashed ID of the capability + /// @param donId The ID of the DON that requires the capability + error CapabilityRequiredByDON(bytes32 hashedCapabilityId, uint32 donId); /// @notice This error is thrown when trying to add a capability with a /// configuration contract that does not implement the required interface. @@ -353,8 +432,6 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice Set of deprecated hashed capability IDs, /// A hashed ID is created by the function `getHashedCapabilityId`. - /// - /// Deprecated capabilities are skipped by the `getCapabilities` function. EnumerableSet.Bytes32Set private s_deprecatedHashedCapabilityIds; /// @notice Encoded node signer addresses @@ -383,7 +460,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { uint32 private s_nextDONId = 1; function typeAndVersion() external pure override returns (string memory) { - return "CapabilityRegistry 1.0.0"; + return "CapabilitiesRegistry 1.0.0"; } /// @notice Adds a list of node operators @@ -469,10 +546,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice Adds nodes. Nodes can be added with deprecated capabilities to /// avoid breaking changes when deprecating capabilities. /// @param nodes The nodes to add - function addNodes(NodeInfo[] calldata nodes) external { + function addNodes(NodeParams[] calldata nodes) external { bool isOwner = msg.sender == owner(); for (uint256 i; i < nodes.length; ++i) { - NodeInfo memory node = nodes[i]; + NodeParams memory node = nodes[i]; NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; if (nodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(node.nodeOperatorId); @@ -515,7 +592,9 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { Node storage node = s_nodes[p2pId]; if (node.signer == bytes32("")) revert NodeDoesNotExist(p2pId); - if (node.supportedDONIds.length() > 0) revert NodePartOfDON(p2pId); + if (node.capabilitiesDONIds.length() > 0) + revert NodePartOfCapabilitiesDON(uint32(node.capabilitiesDONIds.at(i)), p2pId); + if (node.workflowDONId != 0) revert NodePartOfWorkflowDON(node.workflowDONId, p2pId); if (!isOwner && msg.sender != s_nodeOperators[node.nodeOperatorId].admin) revert AccessForbidden(msg.sender); s_nodeSigners.remove(node.signer); @@ -528,73 +607,94 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice Updates nodes. The node admin can update the node's signer address /// and reconfigure its supported capabilities /// @param nodes The nodes to update - function updateNodes(NodeInfo[] calldata nodes) external { + function updateNodes(NodeParams[] calldata nodes) external { bool isOwner = msg.sender == owner(); for (uint256 i; i < nodes.length; ++i) { - NodeInfo memory node = nodes[i]; - + NodeParams memory node = nodes[i]; NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); Node storage storedNode = s_nodes[node.p2pId]; if (storedNode.signer == bytes32("")) revert NodeDoesNotExist(node.p2pId); + if (node.signer == bytes32("")) revert InvalidNodeSigner(); - if (node.signer == bytes32("") || (storedNode.signer != node.signer && s_nodeSigners.contains(node.signer))) - revert InvalidNodeSigner(); + bytes32 previousSigner = storedNode.signer; + if (previousSigner != node.signer) { + if (s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); + storedNode.signer = node.signer; + s_nodeSigners.remove(previousSigner); + s_nodeSigners.add(node.signer); + } bytes32[] memory supportedHashedCapabilityIds = node.hashedCapabilityIds; if (supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(supportedHashedCapabilityIds); - storedNode.configCount++; - uint32 capabilityConfigCount = storedNode.configCount; + uint32 capabilityConfigCount = ++storedNode.configCount; for (uint256 j; j < supportedHashedCapabilityIds.length; ++j) { if (!s_hashedCapabilityIds.contains(supportedHashedCapabilityIds[j])) revert InvalidNodeCapabilities(supportedHashedCapabilityIds); storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(supportedHashedCapabilityIds[j]); } - storedNode.nodeOperatorId = node.nodeOperatorId; - storedNode.p2pId = node.p2pId; + // Validate that capabilities required by a Workflow DON are still supported + uint32 nodeWorkflowDONId = storedNode.workflowDONId; + if (nodeWorkflowDONId != 0) { + bytes32[] memory workflowDonCapabilityIds = s_dons[nodeWorkflowDONId] + .config[s_dons[nodeWorkflowDONId].configCount] + .capabilityIds; + + for (uint256 j; j < workflowDonCapabilityIds.length; ++j) { + if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(workflowDonCapabilityIds[j])) + revert CapabilityRequiredByDON(workflowDonCapabilityIds[j], nodeWorkflowDONId); + } + } - bytes32 previousSigner = storedNode.signer; + // Validate that capabilities required by capabilities DONs are still supported + uint256[] memory capabilitiesDONIds = storedNode.capabilitiesDONIds.values(); + for (uint32 j; j < capabilitiesDONIds.length; ++j) { + uint32 donId = uint32(capabilitiesDONIds[j]); + bytes32[] memory donCapabilityIds = s_dons[donId].config[s_dons[donId].configCount].capabilityIds; - if (storedNode.signer != node.signer) { - s_nodeSigners.remove(previousSigner); - storedNode.signer = node.signer; - s_nodeSigners.add(node.signer); + for (uint256 k; k < donCapabilityIds.length; ++k) { + if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(donCapabilityIds[k])) + revert CapabilityRequiredByDON(donCapabilityIds[k], donId); + } } + + storedNode.nodeOperatorId = node.nodeOperatorId; + storedNode.p2pId = node.p2pId; + emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer); } } /// @notice Gets a node's data /// @param p2pId The P2P ID of the node to query for - /// @return NodeInfo The node data - /// @return configCount The number of times the node has been configured - function getNode(bytes32 p2pId) public view returns (NodeInfo memory, uint32 configCount) { + /// @return nodeInfo NodeInfo The node data + function getNode(bytes32 p2pId) public view returns (NodeInfo memory nodeInfo) { return ( NodeInfo({ nodeOperatorId: s_nodes[p2pId].nodeOperatorId, p2pId: s_nodes[p2pId].p2pId, signer: s_nodes[p2pId].signer, - hashedCapabilityIds: s_nodes[p2pId].supportedHashedCapabilityIds[s_nodes[p2pId].configCount].values() - }), - s_nodes[p2pId].configCount + hashedCapabilityIds: s_nodes[p2pId].supportedHashedCapabilityIds[s_nodes[p2pId].configCount].values(), + configCount: s_nodes[p2pId].configCount, + workflowDONId: s_nodes[p2pId].workflowDONId, + capabilitiesDONIds: s_nodes[p2pId].capabilitiesDONIds.values() + }) ); } /// @notice Gets all nodes - /// @return nodeInfo NodeInfo[] All nodes in the capability registry - /// @return configCounts uint32[] All the config counts for the nodes in the capability registry - function getNodes() external view returns (NodeInfo[] memory nodeInfo, uint32[] memory configCounts) { + /// @return NodeInfo[] All nodes in the capability registry + function getNodes() external view returns (NodeInfo[] memory) { bytes32[] memory p2pIds = s_nodeP2PIds.values(); - nodeInfo = new NodeInfo[](p2pIds.length); - configCounts = new uint32[](p2pIds.length); + NodeInfo[] memory nodesInfo = new NodeInfo[](p2pIds.length); for (uint256 i; i < p2pIds.length; ++i) { - (nodeInfo[i], configCounts[i]) = getNode(p2pIds[i]); + nodesInfo[i] = getNode(p2pIds[i]); } - return (nodeInfo, configCounts); + return nodesInfo; } /// @notice Adds a new capability to the capability registry @@ -619,47 +719,38 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { if (!s_hashedCapabilityIds.contains(hashedCapabilityId)) revert CapabilityDoesNotExist(hashedCapabilityId); if (!s_deprecatedHashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityIsDeprecated(hashedCapabilityId); - delete s_capabilities[hashedCapabilityId]; emit CapabilityDeprecated(hashedCapabilityId); } } /// @notice Returns a Capability by its hashed ID. /// @dev Use `getHashedCapabilityId` to get the hashed ID. - function getCapability(bytes32 hashedId) external view returns (Capability memory) { - return s_capabilities[hashedId]; + function getCapability(bytes32 hashedId) public view returns (CapabilityInfo memory) { + return ( + CapabilityInfo({ + hashedId: hashedId, + labelledName: s_capabilities[hashedId].labelledName, + version: s_capabilities[hashedId].version, + capabilityType: s_capabilities[hashedId].capabilityType, + responseType: s_capabilities[hashedId].responseType, + configurationContract: s_capabilities[hashedId].configurationContract, + isDeprecated: s_deprecatedHashedCapabilityIds.contains(hashedId) + }) + ); } /// @notice Returns all capabilities. This operation will copy capabilities /// to memory, which can be quite expensive. This is designed to mostly be /// used by view accessors that are queried without any gas fees. - /// @return bytes32[] List of hashed capability Ids - /// @return Capability[] List of capabilities - function getCapabilities() external view returns (bytes32[] memory, Capability[] memory) { + /// @return CapabilityInfo[] List of capabilities + function getCapabilities() external view returns (CapabilityInfo[] memory) { bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values(); - - uint256 numSupportedCapabilities = hashedCapabilityIds.length - s_deprecatedHashedCapabilityIds.length(); - - // Solidity does not support dynamic arrays in memory, so we create a - // fixed-size array and copy the capabilities into it. - Capability[] memory capabilities = new Capability[](numSupportedCapabilities); - bytes32[] memory supportedHashedCapabilityIds = new bytes32[](numSupportedCapabilities); - - // We need to keep track of the new index because we are skipping - // deprecated capabilities. - uint256 newIndex; + CapabilityInfo[] memory capabilitiesInfo = new CapabilityInfo[](hashedCapabilityIds.length); for (uint256 i; i < hashedCapabilityIds.length; ++i) { - bytes32 hashedCapabilityId = hashedCapabilityIds[i]; - - if (!s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId)) { - capabilities[newIndex] = s_capabilities[hashedCapabilityId]; - supportedHashedCapabilityIds[newIndex] = hashedCapabilityId; - ++newIndex; - } + capabilitiesInfo[i] = getCapability(hashedCapabilityIds[i]); } - - return (supportedHashedCapabilityIds, capabilities); + return capabilitiesInfo; } /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access @@ -689,7 +780,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { CapabilityConfiguration[] calldata capabilityConfigurations, bool isPublic, bool acceptsWorkflows, - uint32 f + uint8 f ) external onlyOwner { uint32 id = s_nextDONId++; s_dons[id].id = id; @@ -715,7 +806,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { CapabilityConfiguration[] calldata capabilityConfigurations, bool isPublic, bool acceptsWorkflows, - uint32 f + uint8 f ) external onlyOwner { uint32 configCount = s_dons[donId].configCount; if (configCount == 0) revert DONDoesNotExist(donId); @@ -736,8 +827,13 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { uint32 configCount = don.configCount; EnumerableSet.Bytes32Set storage nodeP2PIds = don.config[configCount].nodes; + bool isWorkflowDON = don.acceptsWorkflows; for (uint256 j; j < nodeP2PIds.length(); ++j) { - s_nodes[nodeP2PIds.at(j)].supportedDONIds.remove(donId); + if (isWorkflowDON) { + delete s_nodes[nodeP2PIds.at(j)].workflowDONId; + } else { + s_nodes[nodeP2PIds.at(j)].capabilitiesDONIds.remove(donId); + } } // DON config count starts at index 1 @@ -823,16 +919,23 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { // needed as the previous config will be overwritten by storing the latest config // at configCount for (uint256 i; i < prevDONCapabilityConfig.nodes.length(); ++i) { - s_nodes[prevDONCapabilityConfig.nodes.at(i)].supportedDONIds.remove(donParams.id); + s_nodes[prevDONCapabilityConfig.nodes.at(i)].capabilitiesDONIds.remove(donParams.id); + delete s_nodes[prevDONCapabilityConfig.nodes.at(i)].workflowDONId; } } for (uint256 i; i < nodes.length; ++i) { if (!donCapabilityConfig.nodes.add(nodes[i])) revert DuplicateDONNode(donParams.id, nodes[i]); - /// Fine to add a duplicate DON ID to the set of supported DON IDs again as the set - /// will only store unique DON IDs - s_nodes[nodes[i]].supportedDONIds.add(donParams.id); + if (donParams.acceptsWorkflows) { + if (s_nodes[nodes[i]].workflowDONId != donParams.id && s_nodes[nodes[i]].workflowDONId != 0) + revert NodePartOfWorkflowDON(donParams.id, nodes[i]); + s_nodes[nodes[i]].workflowDONId = donParams.id; + } else { + /// Fine to add a duplicate DON ID to the set of supported DON IDs again as the set + /// will only store unique DON IDs + s_nodes[nodes[i]].capabilitiesDONIds.add(donParams.id); + } } for (uint256 i; i < capabilityConfigurations.length; ++i) { diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index e886c6011d..9dc6f67560 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -1,80 +1,78 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {IReceiver} from "./interfaces/IReceiver.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -contract KeystoneFeedsConsumer is IReceiver, ConfirmedOwner { - event FeedReceived(bytes32 indexed feedId, int192 price, uint32 timestamp); +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator { + event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); error UnauthorizedSender(address sender); error UnauthorizedWorkflowOwner(address workflowOwner); error UnauthorizedWorkflowName(bytes10 workflowName); - constructor() ConfirmedOwner(msg.sender) {} - struct ReceivedFeedReport { bytes32 FeedId; - int192 Price; + uint224 Price; uint32 Timestamp; } struct StoredFeedReport { - int192 Price; + uint224 Price; uint32 Timestamp; } mapping(bytes32 feedId => StoredFeedReport feedReport) internal s_feedReports; address[] internal s_allowedSendersList; - mapping(address => bool) internal s_allowedSenders; + mapping(address sender => bool) internal s_allowedSenders; address[] internal s_allowedWorkflowOwnersList; - mapping(address => bool) internal s_allowedWorkflowOwners; + mapping(address owner => bool) internal s_allowedWorkflowOwners; bytes10[] internal s_allowedWorkflowNamesList; - mapping(bytes10 => bool) internal s_allowedWorkflowNames; + mapping(bytes10 workflowName => bool) internal s_allowedWorkflowNames; function setConfig( address[] calldata _allowedSendersList, address[] calldata _allowedWorkflowOwnersList, bytes10[] calldata _allowedWorkflowNamesList ) external onlyOwner { - for (uint32 i = 0; i < s_allowedSendersList.length; i++) { + for (uint32 i = 0; i < s_allowedSendersList.length; ++i) { s_allowedSenders[s_allowedSendersList[i]] = false; } - for (uint32 i = 0; i < _allowedSendersList.length; i++) { + for (uint32 i = 0; i < _allowedSendersList.length; ++i) { s_allowedSenders[_allowedSendersList[i]] = true; } s_allowedSendersList = _allowedSendersList; - for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; i++) { + for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; ++i) { s_allowedWorkflowOwners[s_allowedWorkflowOwnersList[i]] = false; } - for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; i++) { + for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; ++i) { s_allowedWorkflowOwners[_allowedWorkflowOwnersList[i]] = true; } s_allowedWorkflowOwnersList = _allowedWorkflowOwnersList; - for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; i++) { + for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; ++i) { s_allowedWorkflowNames[s_allowedWorkflowNamesList[i]] = false; } - for (uint32 i = 0; i < _allowedWorkflowNamesList.length; i++) { + for (uint32 i = 0; i < _allowedWorkflowNamesList.length; ++i) { s_allowedWorkflowNames[_allowedWorkflowNamesList[i]] = true; } s_allowedWorkflowNamesList = _allowedWorkflowNamesList; } function onReport(bytes calldata metadata, bytes calldata rawReport) external { - if (s_allowedSenders[msg.sender] == false) { + if (!s_allowedSenders[msg.sender]) { revert UnauthorizedSender(msg.sender); } (bytes10 workflowName, address workflowOwner) = _getInfo(metadata); - if (s_allowedWorkflowNames[workflowName] == false) { + if (!s_allowedWorkflowNames[workflowName]) { revert UnauthorizedWorkflowName(workflowName); } - if (s_allowedWorkflowOwners[workflowOwner] == false) { + if (!s_allowedWorkflowOwners[workflowOwner]) { revert UnauthorizedWorkflowOwner(workflowOwner); } ReceivedFeedReport[] memory feeds = abi.decode(rawReport, (ReceivedFeedReport[])); - for (uint32 i = 0; i < feeds.length; i++) { + for (uint256 i = 0; i < feeds.length; ++i) { s_feedReports[feeds[i].FeedId] = StoredFeedReport(feeds[i].Price, feeds[i].Timestamp); emit FeedReceived(feeds[i].FeedId, feeds[i].Price, feeds[i].Timestamp); } @@ -95,7 +93,7 @@ contract KeystoneFeedsConsumer is IReceiver, ConfirmedOwner { } } - function getPrice(bytes32 feedId) external view returns (int192, uint32) { + function getPrice(bytes32 feedId) external view returns (uint224, uint32) { StoredFeedReport memory report = s_feedReports[feedId]; return (report.Price, report.Timestamp); } diff --git a/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/contracts/src/v0.8/keystone/KeystoneForwarder.sol index e8885bb754..4b44feccbf 100644 --- a/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ b/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -1,25 +1,21 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; -import {IForwarder} from "./interfaces/IForwarder.sol"; import {IReceiver} from "./interfaces/IReceiver.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {IRouter} from "./interfaces/IRouter.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; /// @notice This is an entry point for `write_${chain}` Target capability. It /// allows nodes to determine if reports have been processed (successfully or /// not) in a decentralized and product-agnostic way by recording processed /// reports. -contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterface { - error ReentrantCall(); - +contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { /// @notice This error is returned when the report is shorter than /// REPORT_METADATA_LENGTH, which is the minimum length of a report. error InvalidReport(); - /// @notice This error is returned when the metadata version is not supported. - error InvalidVersion(uint8 version); - /// @notice This error is thrown whenever trying to set a config with a fault /// tolerance of 0. error FaultToleranceMustBePositive(); @@ -49,9 +45,8 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac /// @notice This error is thrown whenever a report specifies a configuration that /// does not exist. - /// @param donId The DON ID that was provided in the report - /// @param configVersion The config version that was provided in the report - error InvalidConfig(uint32 donId, uint32 configVersion); + /// @param configId (uint64(donId) << 32) | configVersion + error InvalidConfig(uint64 configId); /// @notice This error is thrown whenever a signer address is not in the /// configuration. @@ -62,187 +57,213 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac /// @param signature The signature that was invalid error InvalidSignature(bytes signature); - /// @notice This error is thrown whenever a message has already been processed. - /// @param messageId The ID of the message that was already processed - error AlreadyProcessed(bytes32 messageId); - - bool internal s_reentrancyGuard; // guard against reentrancy - /// @notice Contains the signing address of each oracle struct OracleSet { uint8 f; // Number of faulty nodes allowed address[] signers; - mapping(address => uint256) _positions; // 1-indexed to detect unset values + mapping(address signer => uint256 position) _positions; // 1-indexed to detect unset values } /// @notice Contains the configuration for each DON ID - // @param configId keccak256(donId, donConfigVersion) - mapping(bytes32 configId => OracleSet) internal s_configs; + // @param configId (uint64(donId) << 32) | configVersion + mapping(uint64 configId => OracleSet) internal s_configs; - struct DeliveryStatus { - address transmitter; - bool success; - } - - mapping(bytes32 reportId => DeliveryStatus status) internal s_reports; + event ConfigSet(uint32 indexed donId, uint32 indexed configVersion, uint8 f, address[] signers); /// @notice Emitted when a report is processed - /// @param receiver The address of the receiver contract - /// @param workflowExecutionId The ID of the workflow execution /// @param result The result of the attempted delivery. True if successful. - event ReportProcessed(address indexed receiver, bytes32 indexed workflowExecutionId, bool result); + event ReportProcessed( + address indexed receiver, + bytes32 indexed workflowExecutionId, + bytes2 indexed reportId, + bool result + ); + + string public constant override typeAndVersion = "Forwarder and Router 1.0.0"; - constructor() ConfirmedOwner(msg.sender) {} + constructor() OwnerIsCreator() { + s_forwarders[address(this)] = true; + } uint256 internal constant MAX_ORACLES = 31; uint256 internal constant METADATA_LENGTH = 109; uint256 internal constant FORWARDER_METADATA_LENGTH = 45; uint256 internal constant SIGNATURE_LENGTH = 65; + // ================================================================ + // │ Router │ + // ================================================================ + + mapping(address forwarder => bool) internal s_forwarders; + mapping(bytes32 transmissionId => TransmissionInfo) internal s_transmissions; + + function addForwarder(address forwarder) external onlyOwner { + s_forwarders[forwarder] = true; + emit ForwarderAdded(forwarder); + } + + function removeForwarder(address forwarder) external onlyOwner { + s_forwarders[forwarder] = false; + emit ForwarderRemoved(forwarder); + } + + function route( + bytes32 transmissionId, + address transmitter, + address receiver, + bytes calldata metadata, + bytes calldata validatedReport + ) public returns (bool) { + if (!s_forwarders[msg.sender]) { + revert UnauthorizedForwarder(); + } + + if (s_transmissions[transmissionId].transmitter != address(0)) revert AlreadyAttempted(transmissionId); + s_transmissions[transmissionId].transmitter = transmitter; + + if (receiver.code.length == 0) return false; + + try IReceiver(receiver).onReport(metadata, validatedReport) { + s_transmissions[transmissionId].success = true; + return true; + } catch { + return false; + } + } + + function getTransmissionId( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) public pure returns (bytes32) { + // This is slightly cheaper compared to + // keccak256(abi.encode(receiver, workflowExecutionId, reportId)); + return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); + } + + /// @notice Get transmitter of a given report or 0x0 if it wasn't transmitted yet + function getTransmitter( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (address) { + return s_transmissions[getTransmissionId(receiver, workflowExecutionId, reportId)].transmitter; + } + + /// @notice Get delivery status of a given report + function getTransmissionState( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (IRouter.TransmissionState) { + bytes32 transmissionId = getTransmissionId(receiver, workflowExecutionId, reportId); + + if (s_transmissions[transmissionId].transmitter == address(0)) return IRouter.TransmissionState.NOT_ATTEMPTED; + return + s_transmissions[transmissionId].success ? IRouter.TransmissionState.SUCCEEDED : IRouter.TransmissionState.FAILED; + } + + function isForwarder(address forwarder) external view returns (bool) { + return s_forwarders[forwarder]; + } + + // ================================================================ + // │ Forwarder │ + // ================================================================ + function setConfig(uint32 donId, uint32 configVersion, uint8 f, address[] calldata signers) external onlyOwner { if (f == 0) revert FaultToleranceMustBePositive(); if (signers.length > MAX_ORACLES) revert ExcessSigners(signers.length, MAX_ORACLES); if (signers.length <= 3 * f) revert InsufficientSigners(signers.length, 3 * f + 1); - bytes32 configId = keccak256(abi.encode(donId, configVersion)); + uint64 configId = (uint64(donId) << 32) | configVersion; // remove any old signer addresses - for (uint256 i; i < s_configs[configId].signers.length; ++i) { - address signer = s_configs[configId].signers[i]; - delete s_configs[configId]._positions[signer]; + for (uint256 i = 0; i < s_configs[configId].signers.length; ++i) { + delete s_configs[configId]._positions[s_configs[configId].signers[i]]; } // add new signer addresses - s_configs[configId].signers = signers; - for (uint256 i; i < signers.length; ++i) { + for (uint256 i = 0; i < signers.length; ++i) { // assign indices, detect duplicates address signer = signers[i]; if (s_configs[configId]._positions[signer] != 0) revert DuplicateSigner(signer); - s_configs[configId]._positions[signer] = uint8(i) + 1; - s_configs[configId].signers.push(signer); + s_configs[configId]._positions[signer] = i + 1; } + s_configs[configId].signers = signers; s_configs[configId].f = f; + + emit ConfigSet(donId, configVersion, f, signers); } function clearConfig(uint32 donId, uint32 configVersion) external onlyOwner { - bytes32 configId = keccak256(abi.encode(donId, configVersion)); + // We are not removing old signer positions, because it is sufficient to + // clear the f value for `report` function. If we decide to restore + // the configId in the future, the setConfig function clears the positions. + s_configs[(uint64(donId) << 32) | configVersion].f = 0; - // remove any old signer addresses - for (uint256 i; i < s_configs[configId].signers.length; ++i) { - address signer = s_configs[configId].signers[i]; - delete s_configs[configId]._positions[signer]; - } - - s_configs[configId].f = 0; + emit ConfigSet(donId, configVersion, 0, new address[](0)); } // send a report to receiver function report( - address receiverAddress, + address receiver, bytes calldata rawReport, bytes calldata reportContext, bytes[] calldata signatures - ) external nonReentrant { + ) external { if (rawReport.length < METADATA_LENGTH) { revert InvalidReport(); } bytes32 workflowExecutionId; bytes2 reportId; - bytes32 configId; { - uint32 donId; - uint32 configVersion; - (workflowExecutionId, donId, configVersion, reportId) = _getMetadata(rawReport); - - configId = keccak256(abi.encode(donId, configVersion)); + uint64 configId; + (workflowExecutionId, configId, reportId) = _getMetadata(rawReport); + OracleSet storage config = s_configs[configId]; - uint8 f = s_configs[configId].f; + uint8 f = config.f; // f can never be 0, so this means the config doesn't actually exist - if (f == 0) revert InvalidConfig(donId, configVersion); + if (f == 0) revert InvalidConfig(configId); if (f + 1 != signatures.length) revert InvalidSignatureCount(f + 1, signatures.length); - } - - bytes32 combinedId = _combinedId(receiverAddress, workflowExecutionId, reportId); - if (s_reports[combinedId].transmitter != address(0)) revert AlreadyProcessed(combinedId); - // validate signatures - { + // validate signatures bytes32 completeHash = keccak256(abi.encodePacked(keccak256(rawReport), reportContext)); - - address[MAX_ORACLES] memory signed; - uint8 index; - for (uint256 i; i < signatures.length; ++i) { - (bytes32 r, bytes32 s, uint8 v) = _splitSignature(signatures[i]); - address signer = ecrecover(completeHash, v + 27, r, s); + address[MAX_ORACLES + 1] memory signed; + for (uint256 i = 0; i < signatures.length; ++i) { + bytes calldata signature = signatures[i]; + if (signature.length != SIGNATURE_LENGTH) revert InvalidSignature(signature); + address signer = ecrecover( + completeHash, + uint8(signature[64]) + 27, + bytes32(signature[0:32]), + bytes32(signature[32:64]) + ); // validate signer is trusted and signature is unique - index = uint8(s_configs[configId]._positions[signer]); + uint256 index = config._positions[signer]; if (index == 0) revert InvalidSigner(signer); // index is 1-indexed so we can detect unset signers - index -= 1; if (signed[index] != address(0)) revert DuplicateSigner(signer); signed[index] = signer; } } - bool success; - try - IReceiver(receiverAddress).onReport( - rawReport[FORWARDER_METADATA_LENGTH:METADATA_LENGTH], - rawReport[METADATA_LENGTH:] - ) - { - success = true; - } catch { - // Do nothing, success is already false - } - - s_reports[combinedId] = DeliveryStatus(msg.sender, success); - emit ReportProcessed(receiverAddress, workflowExecutionId, success); - } - - function _combinedId(address receiver, bytes32 workflowExecutionId, bytes2 reportId) internal pure returns (bytes32) { - // TODO: gas savings: could we just use a bytes key and avoid another keccak256 call - return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); - } + bool success = this.route( + getTransmissionId(receiver, workflowExecutionId, reportId), + msg.sender, + receiver, + rawReport[FORWARDER_METADATA_LENGTH:METADATA_LENGTH], + rawReport[METADATA_LENGTH:] + ); - // get transmitter of a given report or 0x0 if it wasn't transmitted yet - function getTransmitter( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) external view returns (address) { - bytes32 combinedId = _combinedId(receiver, workflowExecutionId, reportId); - return s_reports[combinedId].transmitter; - } - - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _splitSignature(bytes memory sig) internal pure returns (bytes32 r, bytes32 s, uint8 v) { - if (sig.length != SIGNATURE_LENGTH) revert InvalidSignature(sig); - - assembly { - /* - First 32 bytes stores the length of the signature - - add(sig, 32) = pointer of sig + 32 - effectively, skips first 32 bytes of signature - - mload(p) loads next 32 bytes starting at the memory address p into memory - */ - - // first 32 bytes, after the length prefix - r := mload(add(sig, 32)) - // second 32 bytes - s := mload(add(sig, 64)) - // final byte (first byte of the next 32 bytes) - v := byte(0, mload(add(sig, 96))) - } + emit ReportProcessed(receiver, workflowExecutionId, reportId, success); } // solhint-disable-next-line chainlink-solidity/explicit-returns function _getMetadata( bytes memory rawReport - ) internal pure returns (bytes32 workflowExecutionId, uint32 donId, uint32 donConfigVersion, bytes2 reportId) { + ) internal pure returns (bytes32 workflowExecutionId, uint64 configId, bytes2 reportId) { // (first 32 bytes of memory contain length of the report) // version // offset 32, size 1 // workflow_execution_id // offset 33, size 32 @@ -252,32 +273,12 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac // workflow_cid // offset 77, size 32 // workflow_name // offset 109, size 10 // workflow_owner // offset 119, size 20 - // report_name // offset 139, size 2 - if (uint8(rawReport[0]) != 1) { - revert InvalidVersion(uint8(rawReport[0])); - } + // report_id // offset 139, size 2 assembly { workflowExecutionId := mload(add(rawReport, 33)) - // shift right by 28 bytes to get the actual value - donId := shr(mul(28, 8), mload(add(rawReport, 69))) - // shift right by 28 bytes to get the actual value - donConfigVersion := shr(mul(28, 8), mload(add(rawReport, 73))) + // shift right by 24 bytes to get the combined don_id and don_config_version + configId := shr(mul(24, 8), mload(add(rawReport, 69))) reportId := mload(add(rawReport, 139)) } } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "KeystoneForwarder 1.0.0"; - } - - /** - * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_reentrancyGuard) revert ReentrantCall(); - s_reentrancyGuard = true; - _; - s_reentrancyGuard = false; - } } diff --git a/contracts/src/v0.8/keystone/OCR3Capability.sol b/contracts/src/v0.8/keystone/OCR3Capability.sol index 872ff7e910..8613a803b2 100644 --- a/contracts/src/v0.8/keystone/OCR3Capability.sol +++ b/contracts/src/v0.8/keystone/OCR3Capability.sol @@ -1,28 +1,20 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; +pragma solidity ^0.8.19; -import {OCR2Base} from "../shared/ocr2/OCR2Base.sol"; +import {OCR2Base} from "./ocr/OCR2Base.sol"; // OCR2Base provides config management compatible with OCR3 contract OCR3Capability is OCR2Base { error ReportingUnsupported(); - constructor() OCR2Base(true) {} + constructor() OCR2Base() {} function typeAndVersion() external pure override returns (string memory) { - return "Keystone 0.0.0"; + return "Keystone 1.0.0"; } - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal override {} - - function _afterSetConfig(uint8 _f, bytes memory _onchainConfig) internal override {} - - function _validateReport( - bytes32 /* configDigest */, - uint40 /* epochAndRound */, - bytes memory /* report */ - ) internal pure override returns (bool) { - return true; + function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { + // no-op } function _report( diff --git a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol index 4deaaa4443..429c2a1d3a 100644 --- a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol +++ b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol @@ -16,7 +16,7 @@ interface ICapabilityConfiguration { /// @notice Returns the capability configuration for a particular DON instance. /// @dev donId is required to get DON-specific configuration. It avoids a /// situation where configuration size grows too large. - /// @param donId The DON instance ID. These are stored in the CapabilityRegistry. + /// @param donId The DON instance ID. These are stored in the CapabilitiesRegistry. /// @return configuration DON's configuration for the capability. function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration); diff --git a/contracts/src/v0.8/keystone/interfaces/IForwarder.sol b/contracts/src/v0.8/keystone/interfaces/IForwarder.sol deleted file mode 100644 index ce9512c657..0000000000 --- a/contracts/src/v0.8/keystone/interfaces/IForwarder.sol +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title IForwarder - forwards keystone reports to a target -interface IForwarder {} diff --git a/contracts/src/v0.8/keystone/interfaces/IRouter.sol b/contracts/src/v0.8/keystone/interfaces/IRouter.sol new file mode 100644 index 0000000000..a36c17c14d --- /dev/null +++ b/contracts/src/v0.8/keystone/interfaces/IRouter.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title IRouter - delivers keystone reports to receiver +interface IRouter { + error UnauthorizedForwarder(); + error AlreadyAttempted(bytes32 transmissionId); + + event ForwarderAdded(address indexed forwarder); + event ForwarderRemoved(address indexed forwarder); + + enum TransmissionState { + NOT_ATTEMPTED, + SUCCEEDED, + FAILED + } + + struct TransmissionInfo { + address transmitter; + bool success; + } + + function addForwarder(address forwarder) external; + function removeForwarder(address forwarder) external; + + function route( + bytes32 transmissionId, + address transmitter, + address receiver, + bytes calldata metadata, + bytes calldata report + ) external returns (bool); + + function getTransmissionId( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external pure returns (bytes32); + function getTransmitter( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (address); + function getTransmissionState( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (TransmissionState); + function isForwarder(address forwarder) external view returns (bool); +} diff --git a/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol b/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol new file mode 100644 index 0000000000..083a404534 --- /dev/null +++ b/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /** + * @notice triggers a new run of the offchain reporting protocol + * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + * @param configDigest configDigest of this configuration + * @param configCount ordinal number of this config setting among all config settings over the life of this contract + * @param signers ith element is address ith oracle uses to sign a report + * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param transmitters addresses oracles use to transmit the reports + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + /** + * @notice optionally emited to indicate the latest configDigest and epoch for + which a report was successfully transmited. Alternatively, the contract may + use latestConfigDigestAndEpoch with scanLogs set to false. + */ + event Transmitted(bytes32 configDigest, uint32 epoch); + + /** + * @notice optionally returns the latest configDigest and epoch for which a + report was successfully transmitted. Alternatively, the contract may return + scanLogs set to true and use Transmitted events to provide this information + to offchain watchers. + * @return scanLogs indicates whether to rely on the configDigest and epoch + returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/contracts/src/v0.8/keystone/ocr/OCR2Base.sol b/contracts/src/v0.8/keystone/ocr/OCR2Base.sol new file mode 100644 index 0000000000..efc7992e90 --- /dev/null +++ b/contracts/src/v0.8/keystone/ocr/OCR2Base.sol @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {OCR2Abstract} from "./OCR2Abstract.sol"; + +/** + * @notice Onchain verification of reports from the offchain reporting protocol + * @dev For details on its operation, see the offchain reporting protocol design + * doc, which refers to this contract as simply the "contract". + */ +abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { + error ReportInvalid(string message); + error InvalidConfig(string message); + + constructor() ConfirmedOwner(msg.sender) {} + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems + // to extract config from logs. + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a single SLOAD. If any further fields are + // added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // TODO: could be optimized by squeezing into one slot + uint8 n; + } + ConfigInfo internal s_configInfo; + + // Used for s_oracles[a].role, where a is an address, to track the purpose + // of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // Index of oracle in s_signers/s_transmitters + Role role; // Role of the address which mapped to this struct + } + + mapping(address signerOrTransmitter => Oracle) internal s_oracles; + + // s_signers contains the signing address of each oracle + address[] internal s_signers; + + // s_transmitters contains the transmission address of each oracle, + // i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + /* + * Config logic + */ + + // Reverts transaction if config args are invalid + modifier checkConfigValid( + uint256 numSigners, + uint256 numTransmitters, + uint256 f + ) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + // solhint-disable-next-line gas-struct-packing + struct SetConfigArgs { + address[] signers; + address[] transmitters; + uint8 f; + bytes onchainConfig; + uint64 offchainConfigVersion; + bytes offchainConfig; + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param _signers addresses with which oracles sign the reports + * @param _transmitters addresses oracles use to transmit the reports + * @param _f number of faulty oracles the system can tolerate + * @param _onchainConfig encoded on-chain contract configuration + * @param _offchainConfigVersion version number for offchainEncoding schema + * @param _offchainConfig encoded off-chain oracle configuration + */ + function setConfig( + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + SetConfigArgs memory args = SetConfigArgs({ + signers: _signers, + transmitters: _transmitters, + f: _f, + onchainConfig: _onchainConfig, + offchainConfigVersion: _offchainConfigVersion, + offchainConfig: _offchainConfig + }); + + _beforeSetConfig(args.f, args.onchainConfig); + + while (s_signers.length != 0) { + // remove any old signer/transmitter addresses + uint256 lastIdx = s_signers.length - 1; + address signer = s_signers[lastIdx]; + address transmitter = s_transmitters[lastIdx]; + delete s_oracles[signer]; + delete s_oracles[transmitter]; + s_signers.pop(); + s_transmitters.pop(); + } + + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < args.signers.length; i++) { + if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); + if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); + // add new signer/transmitter addresses + if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); + s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); + if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); + s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); + s_signers.push(args.signers[i]); + s_transmitters.push(args.transmitters[i]); + } + s_configInfo.f = args.f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + s_configInfo.n = uint8(args.signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + + function _configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /** + * @return list of addresses permitted to transmit reports to this contract + * @dev The list will match the order used to specify the transmitter during setConfig + */ + function transmitters() external view returns (address[] memory) { + return s_transmitters; + } + + function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + /** + * @dev hook called after the report has been fully validated + * for the extending contract to handle additional logic, such as oracle payment + * @param initialGas the amount of gas before validation + * @param transmitter the address of the account that submitted the report + * @param signers the addresses of all signing accounts + * @param report serialized report + */ + function _report( + uint256 initialGas, + address transmitter, + uint8 signerCount, + address[MAX_NUM_ORACLES] memory signers, + bytes calldata report + ) internal virtual; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32 + // word containing length of ss + 0; // placeholder + + function _requireExpectedMsgDataLength( + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss + ) private pure { + // calldata will never be big enough to make this overflow + uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32 + // 32 bytes per entry in _ss + 0; // placeholder + if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); + } + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + uint256 initialGas = gasleft(); // This line must come first + + { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + uint32 epochAndRound = uint32(uint256(reportContext[1])); + + emit Transmitted(configDigest, uint32(epochAndRound >> 8)); + + // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest + // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router + // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); + + _requireExpectedMsgDataLength(report, rs, ss); + + uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; + + if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); + if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); + + Oracle memory transmitter = s_oracles[msg.sender]; + if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) + revert ReportInvalid("unauthorized transmitter"); + } + + address[MAX_NUM_ORACLES] memory signed; + uint8 signerCount = 0; + + { + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + Oracle memory o; + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < rs.length; ++i) { + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_oracles[signer]; + if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); + if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); + signed[o.index] = signer; + signerCount += 1; + } + } + + _report(initialGas, msg.sender, signerCount, signed, report); + } +} diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 795bb40843..e637406c14 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -4,53 +4,59 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {Constants} from "./Constants.t.sol"; import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; contract BaseTest is Test, Constants { - CapabilityRegistry internal s_capabilityRegistry; + CapabilitiesRegistry internal s_CapabilitiesRegistry; CapabilityConfigurationContract internal s_capabilityConfigurationContract; - CapabilityRegistry.Capability internal s_basicCapability; - CapabilityRegistry.Capability internal s_capabilityWithConfigurationContract; + CapabilitiesRegistry.Capability internal s_basicCapability; + CapabilitiesRegistry.Capability internal s_capabilityWithConfigurationContract; bytes32 internal s_basicHashedCapabilityId; bytes32 internal s_capabilityWithConfigurationContractId; bytes32 internal s_nonExistentHashedCapabilityId; function setUp() public virtual { vm.startPrank(ADMIN); - s_capabilityRegistry = new CapabilityRegistry(); + s_CapabilitiesRegistry = new CapabilitiesRegistry(); s_capabilityConfigurationContract = new CapabilityConfigurationContract(); - s_basicCapability = CapabilityRegistry.Capability({ + s_basicCapability = CapabilitiesRegistry.Capability({ labelledName: "data-streams-reports", version: "1.0.0", - responseType: CapabilityRegistry.CapabilityResponseType.REPORT, + responseType: CapabilitiesRegistry.CapabilityResponseType.REPORT, configurationContract: address(0), - capabilityType: CapabilityRegistry.CapabilityType.TRIGGER + capabilityType: CapabilitiesRegistry.CapabilityType.TRIGGER }); - s_capabilityWithConfigurationContract = CapabilityRegistry.Capability({ + s_capabilityWithConfigurationContract = CapabilitiesRegistry.Capability({ labelledName: "read-ethereum-mainnet-gas-price", version: "1.0.2", - responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, + responseType: CapabilitiesRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, configurationContract: address(s_capabilityConfigurationContract), - capabilityType: CapabilityRegistry.CapabilityType.ACTION + capabilityType: CapabilitiesRegistry.CapabilityType.ACTION }); - s_basicHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicHashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityWithConfigurationContractId = s_capabilityRegistry.getHashedCapabilityId( + s_capabilityWithConfigurationContractId = s_CapabilitiesRegistry.getHashedCapabilityId( s_capabilityWithConfigurationContract.labelledName, s_capabilityWithConfigurationContract.version ); - s_nonExistentHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); + s_nonExistentHashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); } - function _getNodeOperators() internal pure returns (CapabilityRegistry.NodeOperator[] memory) { - CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](3); - nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_ONE_ADMIN, name: NODE_OPERATOR_ONE_NAME}); - nodeOperators[1] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_TWO_ADMIN, name: NODE_OPERATOR_TWO_NAME}); - nodeOperators[2] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_THREE, name: NODE_OPERATOR_THREE_NAME}); + function _getNodeOperators() internal pure returns (CapabilitiesRegistry.NodeOperator[] memory) { + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](3); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NODE_OPERATOR_ONE_ADMIN, + name: NODE_OPERATOR_ONE_NAME + }); + nodeOperators[1] = CapabilitiesRegistry.NodeOperator({ + admin: NODE_OPERATOR_TWO_ADMIN, + name: NODE_OPERATOR_TWO_NAME + }); + nodeOperators[2] = CapabilitiesRegistry.NodeOperator({admin: NODE_OPERATOR_THREE, name: NODE_OPERATOR_THREE_NAME}); return nodeOperators; } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilitiesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol similarity index 56% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilitiesTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol index 6c6b164234..7bee2b783b 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilitiesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol @@ -1,53 +1,51 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -contract CapabilityRegistry_AddCapabilitiesTest is BaseTest { - event CapabilityConfigured(bytes32 indexed hashedCapabilityId); - +contract CapabilitiesRegistry_AddCapabilitiesTest is BaseTest { function test_RevertWhen_CalledByNonAdmin() public { changePrank(STRANGER); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](1); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); capabilities[0] = s_basicCapability; vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_RevertWhen_CapabilityExists() public { - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](1); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); capabilities[0] = s_basicCapability; // Successfully add the capability the first time - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addCapabilities(capabilities); // Try to add the same capability again vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.CapabilityAlreadyExists.selector, s_basicHashedCapabilityId) + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityAlreadyExists.selector, s_basicHashedCapabilityId) ); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_RevertWhen_ConfigurationContractNotDeployed() public { address nonExistentContract = address(1); s_capabilityWithConfigurationContract.configurationContract = nonExistentContract; - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](1); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); capabilities[0] = s_capabilityWithConfigurationContract; vm.expectRevert( abi.encodeWithSelector( - CapabilityRegistry.InvalidCapabilityConfigurationContractInterface.selector, + CapabilitiesRegistry.InvalidCapabilityConfigurationContractInterface.selector, nonExistentContract ) ); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { @@ -62,27 +60,29 @@ contract CapabilityRegistry_AddCapabilitiesTest is BaseTest { abi.encode(false) ); s_capabilityWithConfigurationContract.configurationContract = contractWithoutERC165; - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](1); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); capabilities[0] = s_capabilityWithConfigurationContract; vm.expectRevert( abi.encodeWithSelector( - CapabilityRegistry.InvalidCapabilityConfigurationContractInterface.selector, + CapabilitiesRegistry.InvalidCapabilityConfigurationContractInterface.selector, contractWithoutERC165 ) ); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_AddCapability_NoConfigurationContract() public { - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](1); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); capabilities[0] = s_basicCapability; - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId("data-streams-reports", "1.0.0"); - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit CapabilityConfigured(hashedCapabilityId); - s_capabilityRegistry.addCapabilities(capabilities); - CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(hashedCapabilityId); + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId("data-streams-reports", "1.0.0"); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.CapabilityConfigured(hashedCapabilityId); + s_CapabilitiesRegistry.addCapabilities(capabilities); + CapabilitiesRegistry.CapabilityInfo memory storedCapability = s_CapabilitiesRegistry.getCapability( + hashedCapabilityId + ); assertEq(storedCapability.labelledName, s_basicCapability.labelledName); assertEq(storedCapability.version, s_basicCapability.version); @@ -91,18 +91,20 @@ contract CapabilityRegistry_AddCapabilitiesTest is BaseTest { } function test_AddCapability_WithConfiguration() public { - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](1); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); capabilities[0] = s_capabilityWithConfigurationContract; - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( s_capabilityWithConfigurationContract.labelledName, s_capabilityWithConfigurationContract.version ); - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit CapabilityConfigured(hashedCapabilityId); - s_capabilityRegistry.addCapabilities(capabilities); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.CapabilityConfigured(hashedCapabilityId); + s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(hashedCapabilityId); + CapabilitiesRegistry.CapabilityInfo memory storedCapability = s_CapabilitiesRegistry.getCapability( + hashedCapabilityId + ); assertEq(storedCapability.labelledName, s_capabilityWithConfigurationContract.labelledName); assertEq(storedCapability.version, s_capabilityWithConfigurationContract.version); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol new file mode 100644 index 0000000000..fff6623a59 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_AddDONTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicHashedCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + nodes[2] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, + p2pId: P2P_ID_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + hashedCapabilityIds: capabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + changePrank(ADMIN); + } + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + bytes32[] memory nodes = new bytes32[](1); + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_NodeDoesNotSupportCapability() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.NodeDoesNotSupportCapability.selector, + P2P_ID_TWO, + s_capabilityWithConfigurationContractId + ) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_CapabilityDoesNotExist() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_nonExistentHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_FaultToleranceIsZero() public { + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidFaultTolerance.selector, 0, 1)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, 0); + } + + function test_RevertWhen_DuplicateCapabilityAdded() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_DeprecatedCapabilityAdded() public { + bytes32 capabilityId = s_basicHashedCapabilityId; + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = capabilityId; + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: capabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, capabilityId)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_DuplicateNodeAdded() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONNode.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 2, P2P_ID)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_AddDON() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_THREE; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, 1); + vm.expectCall( + address(s_capabilityConfigurationContract), + abi.encodeWithSelector( + ICapabilityConfiguration.beforeCapabilityConfigSet.selector, + nodes, + CONFIG_CAPABILITY_CONFIG, + 1, + DON_ID + ), + 1 + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); + assertEq(donInfo.id, DON_ID); + assertEq(donInfo.configCount, 1); + assertEq(donInfo.isPublic, true); + assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); + assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); + + (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry + .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); + assertEq(CapabilitiesRegistryDONConfig, BASIC_CAPABILITY_CONFIG); + assertEq(capabilityConfigContractConfig, bytes("")); + + ( + bytes memory CapabilitiesRegistryDONConfigTwo, + bytes memory capabilityConfigContractConfigTwo + ) = s_CapabilitiesRegistry.getCapabilityConfigs(DON_ID, s_capabilityWithConfigurationContractId); + assertEq(CapabilitiesRegistryDONConfigTwo, CONFIG_CAPABILITY_CONFIG); + assertEq(capabilityConfigContractConfigTwo, CONFIG_CAPABILITY_CONFIG); + + assertEq(donInfo.nodeP2PIds.length, nodes.length); + assertEq(donInfo.nodeP2PIds[0], P2P_ID); + assertEq(donInfo.nodeP2PIds[1], P2P_ID_THREE); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol new file mode 100644 index 0000000000..b4f7be9bb2 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_AddNodeOperatorsTest is BaseTest { + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_NodeOperatorAdminAddressZero() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); + nodeOperators[0].admin = address(0); + vm.expectRevert(CapabilitiesRegistry.InvalidNodeOperatorAdmin.selector); + s_CapabilitiesRegistry.addNodeOperators(nodeOperators); + } + + function test_AddNodeOperators() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorAdded( + TEST_NODE_OPERATOR_ONE_ID, + NODE_OPERATOR_ONE_ADMIN, + NODE_OPERATOR_ONE_NAME + ); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorAdded( + TEST_NODE_OPERATOR_TWO_ID, + NODE_OPERATOR_TWO_ADMIN, + NODE_OPERATOR_TWO_NAME + ); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + + CapabilitiesRegistry.NodeOperator memory nodeOperatorOne = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_ONE_ID + ); + assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); + + CapabilitiesRegistry.NodeOperator memory nodeOperatorTwo = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_TWO_ID + ); + assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); + assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol similarity index 57% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol index 7bb4eb43c4..c7c92587cf 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol @@ -1,51 +1,49 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_AddNodesTest is BaseTest { - event NodeAdded(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer); +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +contract CapabilitiesRegistry_AddNodesTest is BaseTest { function setUp() public override { BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; changePrank(ADMIN); - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { changePrank(STRANGER); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.AccessForbidden.selector, STRANGER)); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingNodeWithInvalidNodeOperator() public { changePrank(ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; uint32 invalidNodeOperatorId = 10000; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: invalidNodeOperatorId, // Invalid NOP p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, @@ -53,184 +51,184 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { }); vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) + abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) ); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_SignerAddressEmpty() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: bytes32(""), hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_SignerAddressNotUnique() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); changePrank(NODE_OPERATOR_TWO_ADMIN); // Try adding another node with the same signer address - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingDuplicateP2PId() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeAlreadyExists.selector, P2P_ID)); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeAlreadyExists.selector, P2P_ID)); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_P2PIDEmpty() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: bytes32(""), signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeP2PId.selector, bytes32(""))); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingNodeWithoutCapabilities() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](0); - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingNodeWithInvalidCapability() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_capabilityRegistry.addNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.addNodes(nodes); } - function test_AddsNodeInfo() public { + function test_AddsNodeParams() public { changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectEmit(address(s_capabilityRegistry)); - emit NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - s_capabilityRegistry.addNodes(nodes); + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + s_CapabilitiesRegistry.addNodes(nodes); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); assertEq(node.hashedCapabilityIds.length, 2); assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(configCount, 1); + assertEq(node.configCount, 1); } function test_OwnerCanAddNodes() public { changePrank(ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - vm.expectEmit(address(s_capabilityRegistry)); - emit NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - s_capabilityRegistry.addNodes(nodes); + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + s_CapabilitiesRegistry.addNodes(nodes); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); assertEq(node.hashedCapabilityIds.length, 2); assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(configCount, 1); + assertEq(node.configCount, 1); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapabilitiesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol similarity index 51% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapabilitiesTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol index 74c66f8f58..4d289e7c74 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapabilitiesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol @@ -2,23 +2,21 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_DeprecateCapabilitiesTest is BaseTest { - event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +contract CapabilitiesRegistry_DeprecateCapabilitiesTest is BaseTest { function setUp() public override { BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_RevertWhen_CalledByNonAdmin() public { changePrank(STRANGER); - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( s_basicCapability.labelledName, s_basicCapability.version ); @@ -27,7 +25,7 @@ contract CapabilityRegistry_DeprecateCapabilitiesTest is BaseTest { deprecatedCapabilities[0] = hashedCapabilityId; vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); } function test_RevertWhen_CapabilityDoesNotExist() public { @@ -35,13 +33,13 @@ contract CapabilityRegistry_DeprecateCapabilitiesTest is BaseTest { deprecatedCapabilities[0] = s_nonExistentHashedCapabilityId; vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) ); - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); } function test_RevertWhen_CapabilityIsDeprecated() public { - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( s_basicCapability.labelledName, s_basicCapability.version ); @@ -49,25 +47,25 @@ contract CapabilityRegistry_DeprecateCapabilitiesTest is BaseTest { bytes32[] memory deprecatedCapabilities = new bytes32[](1); deprecatedCapabilities[0] = hashedCapabilityId; - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityIsDeprecated.selector, hashedCapabilityId)); - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, hashedCapabilityId)); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); } function test_DeprecatesCapability() public { - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( s_basicCapability.labelledName, s_basicCapability.version ); bytes32[] memory deprecatedCapabilities = new bytes32[](1); deprecatedCapabilities[0] = hashedCapabilityId; - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); - assertEq(s_capabilityRegistry.isCapabilityDeprecated(hashedCapabilityId), true); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + assertEq(s_CapabilitiesRegistry.isCapabilityDeprecated(hashedCapabilityId), true); } function test_EmitsEvent() public { - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( s_basicCapability.labelledName, s_basicCapability.version ); @@ -75,8 +73,8 @@ contract CapabilityRegistry_DeprecateCapabilitiesTest is BaseTest { bytes32[] memory deprecatedCapabilities = new bytes32[](1); deprecatedCapabilities[0] = hashedCapabilityId; - vm.expectEmit(address(s_capabilityRegistry)); - emit CapabilityDeprecated(hashedCapabilityId); - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.CapabilityDeprecated(hashedCapabilityId); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol new file mode 100644 index 0000000000..9702c62b9c --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_GetCapabilitiesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_ReturnsCapabilities() public { + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = hashedCapabilityId; + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + + CapabilitiesRegistry.CapabilityInfo[] memory capabilities = s_CapabilitiesRegistry.getCapabilities(); + + assertEq(capabilities.length, 2); + + assertEq(capabilities[0].labelledName, "data-streams-reports"); + assertEq(capabilities[0].version, "1.0.0"); + assertEq(uint256(capabilities[0].responseType), uint256(CapabilitiesRegistry.CapabilityResponseType.REPORT)); + assertEq(uint256(capabilities[0].capabilityType), uint256(CapabilitiesRegistry.CapabilityType.TRIGGER)); + assertEq(capabilities[0].configurationContract, address(0)); + assertEq(capabilities[0].hashedId, keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); + assertEq(capabilities[0].isDeprecated, true); + + assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].version, "1.0.2"); + assertEq( + uint256(capabilities[1].responseType), + uint256(CapabilitiesRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) + ); + assertEq(uint256(capabilities[1].capabilityType), uint256(CapabilitiesRegistry.CapabilityType.ACTION)); + assertEq(capabilities[1].configurationContract, address(s_capabilityConfigurationContract)); + assertEq(capabilities[1].hashedId, keccak256(abi.encode(capabilities[1].labelledName, capabilities[1].version))); + assertEq(capabilities[1].isDeprecated, false); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetDONsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol similarity index 69% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_GetDONsTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol index f53803c404..a83b1421d3 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetDONsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol @@ -3,29 +3,27 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; -contract CapabilityRegistry_GetDONsTest is BaseTest { - event ConfigSet(uint32 donId, uint32 configCount); - - CapabilityRegistry.CapabilityConfiguration[] private s_capabilityConfigs; +contract CapabilitiesRegistry_GetDONsTest is BaseTest { + CapabilitiesRegistry.CapabilityConfiguration[] private s_capabilityConfigs; function setUp() public override { BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](2); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); bytes32[] memory capabilityIds = new bytes32[](2); capabilityIds[0] = s_basicHashedCapabilityId; capabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, @@ -35,7 +33,7 @@ contract CapabilityRegistry_GetDONsTest is BaseTest { bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[1] = CapabilityRegistry.NodeInfo({ + nodes[1] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, @@ -43,10 +41,10 @@ contract CapabilityRegistry_GetDONsTest is BaseTest { }); changePrank(NODE_OPERATOR_ONE_ADMIN); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); s_capabilityConfigs.push( - CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }) @@ -57,12 +55,12 @@ contract CapabilityRegistry_GetDONsTest is BaseTest { nodeIds[1] = P2P_ID_TWO; changePrank(ADMIN); - s_capabilityRegistry.addDON(nodeIds, s_capabilityConfigs, true, true, 1); - s_capabilityRegistry.addDON(nodeIds, s_capabilityConfigs, false, false, 1); + s_CapabilitiesRegistry.addDON(nodeIds, s_capabilityConfigs, true, true, 1); + s_CapabilitiesRegistry.addDON(nodeIds, s_capabilityConfigs, false, false, 1); } function test_CorrectlyFetchesDONs() public view { - CapabilityRegistry.DONInfo[] memory dons = s_capabilityRegistry.getDONs(); + CapabilitiesRegistry.DONInfo[] memory dons = s_CapabilitiesRegistry.getDONs(); assertEq(dons.length, 2); assertEq(dons[0].id, DON_ID); assertEq(dons[0].configCount, 1); @@ -82,9 +80,9 @@ contract CapabilityRegistry_GetDONsTest is BaseTest { function test_DoesNotIncludeRemovedDONs() public { uint32[] memory removedDONIDs = new uint32[](1); removedDONIDs[0] = DON_ID; - s_capabilityRegistry.removeDONs(removedDONIDs); + s_CapabilitiesRegistry.removeDONs(removedDONIDs); - CapabilityRegistry.DONInfo[] memory dons = s_capabilityRegistry.getDONs(); + CapabilitiesRegistry.DONInfo[] memory dons = s_CapabilitiesRegistry.getDONs(); assertEq(dons.length, 1); assertEq(dons[0].id, DON_ID_TWO); assertEq(dons[0].configCount, 1); diff --git a/contracts/src/v0.8/keystone/test/CapabiityRegistry_GetHashedCapabilityIdTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol similarity index 61% rename from contracts/src/v0.8/keystone/test/CapabiityRegistry_GetHashedCapabilityIdTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol index 435138c80e..b9a6e6dc97 100644 --- a/contracts/src/v0.8/keystone/test/CapabiityRegistry_GetHashedCapabilityIdTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol @@ -4,9 +4,9 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; -contract CapabilityRegistry_GetHashedCapabilityTest is BaseTest { +contract CapabilitiesRegistry_GetHashedCapabilityTest is BaseTest { string constant CAPABILITY_LABELLED_NAME = "ccip1"; string constant CAPABILITY_VERSION = "1.0.0"; @@ -14,15 +14,15 @@ contract CapabilityRegistry_GetHashedCapabilityTest is BaseTest { bytes32 expectedHashedCapabilityId = keccak256(abi.encode(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION)); assertEq( - s_capabilityRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), + s_CapabilitiesRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), expectedHashedCapabilityId ); } function test_DoesNotCauseIncorrectClashes() public view { assertNotEq( - s_capabilityRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), - s_capabilityRegistry.getHashedCapabilityId("ccip", "11.0.0") + s_CapabilitiesRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), + s_CapabilitiesRegistry.getHashedCapabilityId("ccip", "11.0.0") ); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol similarity index 70% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_GetNodeOperatorsTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol index f1ce3d79ab..36ef201a99 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetNodeOperatorsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol @@ -2,17 +2,17 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; -contract CapabilityRegistry_GetNodeOperatorsTest is BaseTest { +contract CapabilitiesRegistry_GetNodeOperatorsTest is BaseTest { function setUp() public override { BaseTest.setUp(); changePrank(ADMIN); - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); } function test_CorrectlyFetchesNodeOperators() public view { - CapabilityRegistry.NodeOperator[] memory nodeOperators = s_capabilityRegistry.getNodeOperators(); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = s_CapabilitiesRegistry.getNodeOperators(); assertEq(nodeOperators.length, 3); assertEq(nodeOperators[0].admin, NODE_OPERATOR_ONE_ADMIN); @@ -29,9 +29,9 @@ contract CapabilityRegistry_GetNodeOperatorsTest is BaseTest { changePrank(ADMIN); uint32[] memory nodeOperatorsToRemove = new uint32[](1); nodeOperatorsToRemove[0] = 2; - s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); - CapabilityRegistry.NodeOperator[] memory nodeOperators = s_capabilityRegistry.getNodeOperators(); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = s_CapabilitiesRegistry.getNodeOperators(); assertEq(nodeOperators.length, 2); assertEq(nodeOperators[0].admin, NODE_OPERATOR_ONE_ADMIN); diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol similarity index 71% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_GetNodesTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol index 28fc33ab1d..901e7b9272 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol @@ -2,33 +2,33 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; -contract CapabilityRegistry_GetNodesTest is BaseTest { +contract CapabilitiesRegistry_GetNodesTest is BaseTest { function setUp() public override { BaseTest.setUp(); changePrank(ADMIN); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](2); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - nodes[1] = CapabilityRegistry.NodeInfo({ + nodes[1] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, @@ -37,11 +37,11 @@ contract CapabilityRegistry_GetNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); } function test_CorrectlyFetchesNodes() public view { - (CapabilityRegistry.NodeInfo[] memory nodes, uint32[] memory configCounts) = s_capabilityRegistry.getNodes(); + CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodes(); assertEq(nodes.length, 2); assertEq(nodes[0].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); @@ -50,7 +50,7 @@ contract CapabilityRegistry_GetNodesTest is BaseTest { assertEq(nodes[0].hashedCapabilityIds.length, 2); assertEq(nodes[0].hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(nodes[0].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(configCounts[0], 1); + assertEq(nodes[0].configCount, 1); assertEq(nodes[1].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(nodes[1].signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); @@ -58,16 +58,16 @@ contract CapabilityRegistry_GetNodesTest is BaseTest { assertEq(nodes[1].hashedCapabilityIds.length, 2); assertEq(nodes[1].hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(nodes[1].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(configCounts[1], 1); + assertEq(nodes[1].configCount, 1); } function test_DoesNotIncludeRemovedNodes() public { changePrank(ADMIN); bytes32[] memory nodesToRemove = new bytes32[](1); nodesToRemove[0] = P2P_ID_TWO; - s_capabilityRegistry.removeNodes(nodesToRemove); + s_CapabilitiesRegistry.removeNodes(nodesToRemove); - (CapabilityRegistry.NodeInfo[] memory nodes, uint32[] memory configCounts) = s_capabilityRegistry.getNodes(); + CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodes(); assertEq(nodes.length, 1); assertEq(nodes[0].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); @@ -76,6 +76,6 @@ contract CapabilityRegistry_GetNodesTest is BaseTest { assertEq(nodes[0].hashedCapabilityIds.length, 2); assertEq(nodes[0].hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(nodes[0].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(configCounts[0], 1); + assertEq(nodes[0].configCount, 1); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveDONsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol similarity index 55% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveDONsTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol index 8d5bfdeea6..0311ffd6f8 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveDONsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol @@ -1,29 +1,27 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_RemoveDONsTest is BaseTest { - event ConfigSet(uint32 donId, uint32 configCount); +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +contract CapabilitiesRegistry_RemoveDONsTest is BaseTest { function setUp() public override { BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](2); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); bytes32[] memory capabilityIds = new bytes32[](2); capabilityIds[0] = s_basicHashedCapabilityId; capabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, @@ -33,7 +31,7 @@ contract CapabilityRegistry_RemoveDONsTest is BaseTest { bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[1] = CapabilityRegistry.NodeInfo({ + nodes[1] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, @@ -41,11 +39,11 @@ contract CapabilityRegistry_RemoveDONsTest is BaseTest { }); changePrank(NODE_OPERATOR_ONE_ADMIN); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); @@ -55,7 +53,7 @@ contract CapabilityRegistry_RemoveDONsTest is BaseTest { nodeIds[1] = P2P_ID_TWO; changePrank(ADMIN); - s_capabilityRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); + s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); } function test_RevertWhen_CalledByNonAdmin() public { @@ -63,34 +61,34 @@ contract CapabilityRegistry_RemoveDONsTest is BaseTest { donIDs[0] = 1; changePrank(STRANGER); vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.removeDONs(donIDs); + s_CapabilitiesRegistry.removeDONs(donIDs); } function test_RevertWhen_DONDoesNotExist() public { uint32 invalidDONId = 10; uint32[] memory donIDs = new uint32[](1); donIDs[0] = invalidDONId; - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.DONDoesNotExist.selector, invalidDONId)); - s_capabilityRegistry.removeDONs(donIDs); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DONDoesNotExist.selector, invalidDONId)); + s_CapabilitiesRegistry.removeDONs(donIDs); } function test_RemovesDON() public { uint32[] memory donIDs = new uint32[](1); donIDs[0] = DON_ID; - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit ConfigSet(DON_ID, 0); - s_capabilityRegistry.removeDONs(donIDs); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, 0); + s_CapabilitiesRegistry.removeDONs(donIDs); - CapabilityRegistry.DONInfo memory donInfo = s_capabilityRegistry.getDON(DON_ID); + CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); assertEq(donInfo.id, 0); assertEq(donInfo.configCount, 0); assertEq(donInfo.isPublic, false); assertEq(donInfo.capabilityConfigurations.length, 0); - (bytes memory capabilityRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_capabilityRegistry + (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); - assertEq(capabilityRegistryDONConfig, bytes("")); + assertEq(CapabilitiesRegistryDONConfig, bytes("")); assertEq(capabilityConfigContractConfig, bytes("")); assertEq(donInfo.nodeP2PIds.length, 0); } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol similarity index 50% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol index d7aef82459..1f70bc8326 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodeOperatorsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol @@ -1,16 +1,14 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_RemoveNodeOperatorsTest is BaseTest { - event NodeOperatorRemoved(uint32 indexed nodeOperatorId); +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +contract CapabilitiesRegistry_RemoveNodeOperatorsTest is BaseTest { function setUp() public override { BaseTest.setUp(); changePrank(ADMIN); - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); } function test_RevertWhen_CalledByNonOwner() public { @@ -18,28 +16,28 @@ contract CapabilityRegistry_RemoveNodeOperatorsTest is BaseTest { vm.expectRevert("Only callable by owner"); uint32[] memory nodeOperatorsToRemove = new uint32[](2); nodeOperatorsToRemove[1] = 1; - s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); } function test_RemovesNodeOperator() public { changePrank(ADMIN); - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit NodeOperatorRemoved(TEST_NODE_OPERATOR_ONE_ID); - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit NodeOperatorRemoved(TEST_NODE_OPERATOR_TWO_ID); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorRemoved(TEST_NODE_OPERATOR_ONE_ID); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorRemoved(TEST_NODE_OPERATOR_TWO_ID); uint32[] memory nodeOperatorsToRemove = new uint32[](2); nodeOperatorsToRemove[0] = TEST_NODE_OPERATOR_ONE_ID; nodeOperatorsToRemove[1] = TEST_NODE_OPERATOR_TWO_ID; - s_capabilityRegistry.removeNodeOperators(nodeOperatorsToRemove); + s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); - CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator( + CapabilitiesRegistry.NodeOperator memory nodeOperatorOne = s_CapabilitiesRegistry.getNodeOperator( TEST_NODE_OPERATOR_ONE_ID ); assertEq(nodeOperatorOne.admin, address(0)); assertEq(nodeOperatorOne.name, ""); - CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator( + CapabilitiesRegistry.NodeOperator memory nodeOperatorTwo = s_CapabilitiesRegistry.getNodeOperator( TEST_NODE_OPERATOR_TWO_ID ); assertEq(nodeOperatorTwo.admin, address(0)); diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol similarity index 54% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol index ac59435e35..9622c23876 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_RemoveNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol @@ -1,42 +1,40 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_RemoveNodesTest is BaseTest { - event NodeRemoved(bytes32 p2pId); +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { function setUp() public override { BaseTest.setUp(); changePrank(ADMIN); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](3); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - nodes[1] = CapabilityRegistry.NodeInfo({ + nodes[1] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - nodes[2] = CapabilityRegistry.NodeInfo({ + nodes[2] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, @@ -45,7 +43,7 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { changePrank(ADMIN); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { @@ -53,8 +51,8 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = P2P_ID; - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.AccessForbidden.selector, STRANGER)); - s_capabilityRegistry.removeNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.removeNodes(nodes); } function test_RevertWhen_NodeDoesNotExist() public { @@ -62,8 +60,8 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = INVALID_P2P_ID; - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); - s_capabilityRegistry.removeNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); + s_CapabilitiesRegistry.removeNodes(nodes); } function test_RevertWhen_P2PIDEmpty() public { @@ -71,27 +69,27 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = bytes32(""); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, bytes32(""))); - s_capabilityRegistry.removeNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); + s_CapabilitiesRegistry.removeNodes(nodes); } - function test_RevertWhen_NodePartOfDON() public { + function test_RevertWhen_NodePartOfCapabilitiesDON() public { changePrank(ADMIN); bytes32[] memory nodes = new bytes32[](2); nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, false, F_VALUE); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodePartOfDON.selector, P2P_ID)); - s_capabilityRegistry.removeNodes(nodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfCapabilitiesDON.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.removeNodes(nodes); } function test_CanRemoveWhenDONDeleted() public { @@ -101,35 +99,35 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); // Add DON - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); // Try remove nodes bytes32[] memory removedNodes = new bytes32[](1); removedNodes[0] = P2P_ID; - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodePartOfDON.selector, P2P_ID)); - s_capabilityRegistry.removeNodes(removedNodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.removeNodes(removedNodes); // Remove DON uint32[] memory donIds = new uint32[](1); donIds[0] = DON_ID; - s_capabilityRegistry.removeDONs(donIds); + s_CapabilitiesRegistry.removeDONs(donIds); // Remove node - s_capabilityRegistry.removeNodes(removedNodes); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); + s_CapabilitiesRegistry.removeNodes(removedNodes); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, 0); assertEq(node.p2pId, bytes32("")); assertEq(node.signer, bytes32("")); assertEq(node.hashedCapabilityIds.length, 0); - assertEq(configCount, 0); + assertEq(node.configCount, 0); } function test_CanRemoveWhenNodeNoLongerPartOfDON() public { @@ -140,36 +138,36 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { nodes[1] = P2P_ID_TWO; nodes[2] = P2P_ID_THREE; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); // Add DON - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); // Try remove nodes bytes32[] memory removedNodes = new bytes32[](1); removedNodes[0] = P2P_ID_TWO; - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodePartOfDON.selector, P2P_ID_TWO)); - s_capabilityRegistry.removeNodes(removedNodes); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 1, P2P_ID_TWO)); + s_CapabilitiesRegistry.removeNodes(removedNodes); // Update nodes in DON bytes32[] memory updatedNodes = new bytes32[](2); updatedNodes[0] = P2P_ID; updatedNodes[1] = P2P_ID_THREE; - s_capabilityRegistry.updateDON(DON_ID, updatedNodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.updateDON(DON_ID, updatedNodes, capabilityConfigs, true, true, F_VALUE); // Remove node - s_capabilityRegistry.removeNodes(removedNodes); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID_TWO); + s_CapabilitiesRegistry.removeNodes(removedNodes); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID_TWO); assertEq(node.nodeOperatorId, 0); assertEq(node.p2pId, bytes32("")); assertEq(node.signer, bytes32("")); assertEq(node.hashedCapabilityIds.length, 0); - assertEq(configCount, 0); + assertEq(node.configCount, 0); } function test_RemovesNode() public { @@ -178,16 +176,16 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = P2P_ID; - vm.expectEmit(address(s_capabilityRegistry)); - emit NodeRemoved(P2P_ID); - s_capabilityRegistry.removeNodes(nodes); + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeRemoved(P2P_ID); + s_CapabilitiesRegistry.removeNodes(nodes); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, 0); assertEq(node.p2pId, bytes32("")); assertEq(node.signer, bytes32("")); assertEq(node.hashedCapabilityIds.length, 0); - assertEq(configCount, 0); + assertEq(node.configCount, 0); } function test_CanAddNodeWithSameSignerAddressAfterRemoving() public { @@ -196,29 +194,29 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = P2P_ID; - s_capabilityRegistry.removeNodes(nodes); + s_CapabilitiesRegistry.removeNodes(nodes); - CapabilityRegistry.NodeInfo[] memory NodeInfo = new CapabilityRegistry.NodeInfo[](1); + CapabilitiesRegistry.NodeParams[] memory nodeParams = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - NodeInfo[0] = CapabilityRegistry.NodeInfo({ + nodeParams[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, hashedCapabilityIds: hashedCapabilityIds }); - s_capabilityRegistry.addNodes(NodeInfo); + s_CapabilitiesRegistry.addNodes(nodeParams); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); assertEq(node.hashedCapabilityIds.length, 2); assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(configCount, 1); + assertEq(node.configCount, 1); } function test_OwnerCanRemoveNodes() public { @@ -227,15 +225,15 @@ contract CapabilityRegistry_RemoveNodesTest is BaseTest { bytes32[] memory nodes = new bytes32[](1); nodes[0] = P2P_ID; - vm.expectEmit(address(s_capabilityRegistry)); - emit NodeRemoved(P2P_ID); - s_capabilityRegistry.removeNodes(nodes); + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeRemoved(P2P_ID); + s_CapabilitiesRegistry.removeNodes(nodes); - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, 0); assertEq(node.p2pId, bytes32("")); assertEq(node.signer, bytes32("")); assertEq(node.hashedCapabilityIds.length, 0); - assertEq(configCount, 0); + assertEq(node.configCount, 0); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol new file mode 100644 index 0000000000..00ce88f54f --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; + +contract CapabilitiesRegistry_TypeAndVersionTest is BaseTest { + function test_TypeAndVersion() public view { + assertEq(s_CapabilitiesRegistry.typeAndVersion(), "CapabilitiesRegistry 1.0.0"); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateDONTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol similarity index 50% rename from contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateDONTest.t.sol rename to contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol index 1737c19d27..8b21b29506 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateDONTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol @@ -1,29 +1,27 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {BaseTest} from "./BaseTest.t.sol"; import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_UpdateDONTest is BaseTest { - event ConfigSet(uint32 donId, uint32 configCount); +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +contract CapabilitiesRegistry_UpdateDONTest is BaseTest { function setUp() public override { BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](3); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); bytes32[] memory capabilityIds = new bytes32[](2); capabilityIds[0] = s_basicHashedCapabilityId; capabilityIds[1] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilityRegistry.NodeInfo({ + nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, @@ -33,67 +31,67 @@ contract CapabilityRegistry_UpdateDONTest is BaseTest { bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - nodes[1] = CapabilityRegistry.NodeInfo({ + nodes[1] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, hashedCapabilityIds: nodeTwoCapabilityIds }); - nodes[2] = CapabilityRegistry.NodeInfo({ + nodes[2] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, p2pId: P2P_ID_THREE, signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, hashedCapabilityIds: capabilityIds }); - s_capabilityRegistry.addNodes(nodes); + s_CapabilitiesRegistry.addNodes(nodes); bytes32[] memory donNodes = new bytes32[](2); donNodes[0] = P2P_ID; donNodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - s_capabilityRegistry.addDON(donNodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.addDON(donNodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_CalledByNonAdmin() public { changePrank(STRANGER); vm.expectRevert("Only callable by owner"); bytes32[] memory nodes = new bytes32[](1); - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_NodeDoesNotSupportCapability() public { bytes32[] memory nodes = new bytes32[](2); nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_capabilityWithConfigurationContractId, config: CONFIG_CAPABILITY_CONFIG }); vm.expectRevert( abi.encodeWithSelector( - CapabilityRegistry.NodeDoesNotSupportCapability.selector, + CapabilitiesRegistry.NodeDoesNotSupportCapability.selector, P2P_ID_TWO, s_capabilityWithConfigurationContractId ) ); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_DONDoesNotExist() public { @@ -101,30 +99,30 @@ contract CapabilityRegistry_UpdateDONTest is BaseTest { bytes32[] memory nodes = new bytes32[](2); nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.DONDoesNotExist.selector, nonExistentDONId)); - s_capabilityRegistry.updateDON(nonExistentDONId, nodes, capabilityConfigs, true, true, F_VALUE); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DONDoesNotExist.selector, nonExistentDONId)); + s_CapabilitiesRegistry.updateDON(nonExistentDONId, nodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_CapabilityDoesNotExist() public { bytes32[] memory nodes = new bytes32[](2); nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_nonExistentHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) ); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_DuplicateCapabilityAdded() public { @@ -132,42 +130,42 @@ contract CapabilityRegistry_UpdateDONTest is BaseTest { nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - capabilityConfigs[1] = CapabilityRegistry.CapabilityConfiguration({ + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) + abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) ); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_DeprecatedCapabilityAdded() public { bytes32 capabilityId = s_basicHashedCapabilityId; bytes32[] memory deprecatedCapabilities = new bytes32[](1); deprecatedCapabilities[0] = capabilityId; - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); bytes32[] memory nodes = new bytes32[](2); nodes[0] = P2P_ID; nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: capabilityId, config: BASIC_CAPABILITY_CONFIG }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityIsDeprecated.selector, capabilityId)); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, capabilityId)); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); } function test_RevertWhen_DuplicateNodeAdded() public { @@ -175,14 +173,14 @@ contract CapabilityRegistry_UpdateDONTest is BaseTest { nodes[0] = P2P_ID; nodes[1] = P2P_ID; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.DuplicateDONNode.selector, 1, P2P_ID)); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONNode.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, true, F_VALUE); } function test_UpdatesDON() public { @@ -190,24 +188,24 @@ contract CapabilityRegistry_UpdateDONTest is BaseTest { nodes[0] = P2P_ID; nodes[1] = P2P_ID_THREE; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_basicHashedCapabilityId, config: BASIC_CAPABILITY_CONFIG }); - capabilityConfigs[1] = CapabilityRegistry.CapabilityConfiguration({ + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ capabilityId: s_capabilityWithConfigurationContractId, config: CONFIG_CAPABILITY_CONFIG }); - CapabilityRegistry.DONInfo memory oldDONInfo = s_capabilityRegistry.getDON(DON_ID); + CapabilitiesRegistry.DONInfo memory oldDONInfo = s_CapabilitiesRegistry.getDON(DON_ID); bool expectedDONIsPublic = false; uint32 expectedConfigCount = oldDONInfo.configCount + 1; - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit ConfigSet(DON_ID, expectedConfigCount); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, expectedConfigCount); vm.expectCall( address(s_capabilityConfigurationContract), abi.encodeWithSelector( @@ -219,18 +217,18 @@ contract CapabilityRegistry_UpdateDONTest is BaseTest { ), 1 ); - s_capabilityRegistry.updateDON(DON_ID, nodes, capabilityConfigs, expectedDONIsPublic, true, F_VALUE); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, expectedDONIsPublic, true, F_VALUE); - CapabilityRegistry.DONInfo memory donInfo = s_capabilityRegistry.getDON(DON_ID); + CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); assertEq(donInfo.id, DON_ID); assertEq(donInfo.configCount, expectedConfigCount); assertEq(donInfo.isPublic, false); assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - (bytes memory capabilityRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_capabilityRegistry + (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); - assertEq(capabilityRegistryDONConfig, BASIC_CAPABILITY_CONFIG); + assertEq(CapabilitiesRegistryDONConfig, BASIC_CAPABILITY_CONFIG); assertEq(capabilityConfigContractConfig, bytes("")); assertEq(donInfo.nodeP2PIds.length, nodes.length); diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol new file mode 100644 index 0000000000..e0d1742c98 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_UpdateNodeOperatorTest is BaseTest { + uint32 private constant TEST_NODE_OPERATOR_ID = 1; + address private constant NEW_NODE_OPERATOR_ADMIN = address(3); + string private constant NEW_NODE_OPERATOR_NAME = "new-node-operator"; + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_CalledByNonAdminAndNonOwner() public { + changePrank(STRANGER); + + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorAdminIsZeroAddress() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({admin: address(0), name: NEW_NODE_OPERATOR_NAME}); + + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectRevert(CapabilitiesRegistry.InvalidNodeOperatorAdmin.selector); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32 invalidNodeOperatorId = 10000; + uint32[] memory nodeOperatorIds = new uint32[](2); + nodeOperatorIds[0] = invalidNodeOperatorId; + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.LengthMismatch.selector, nodeOperatorIds.length, nodeOperators.length) + ); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorDoesNotExist() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32 invalidNodeOperatorId = 10000; + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = invalidNodeOperatorId; + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) + ); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_UpdatesNodeOperator() public { + changePrank(ADMIN); + + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorUpdated( + TEST_NODE_OPERATOR_ID, + NEW_NODE_OPERATOR_ADMIN, + NEW_NODE_OPERATOR_NAME + ); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + + CapabilitiesRegistry.NodeOperator memory nodeOperator = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_ID + ); + assertEq(nodeOperator.admin, NEW_NODE_OPERATOR_ADMIN); + assertEq(nodeOperator.name, NEW_NODE_OPERATOR_NAME); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol new file mode 100644 index 0000000000..43c6adc35b --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + s_CapabilitiesRegistry.addNodes(nodes); + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_TWO_ADMIN); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_NodeDoesNotExist() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: INVALID_P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: bytes32(""), + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: bytes32(""), + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(CapabilitiesRegistry.InvalidNodeSigner.selector); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_UpdatingNodeWithoutCapabilities() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](0); + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidCapability() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() public { + // SETUP: addDON + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + bytes32[] memory nodeIds = new bytes32[](2); + nodeIds[0] = P2P_ID; + nodeIds[1] = P2P_ID_TWO; + + // SETUP: updateNodes + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + // DON requires s_basicHashedCapabilityId but we are swapping for + // s_capabilityWithConfigurationContractId + hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + uint32 workflowDonId = 1; + + // Operations + changePrank(ADMIN); + s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); + + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.CapabilityRequiredByDON.selector, + s_basicHashedCapabilityId, + workflowDonId + ) + ); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() public { + // SETUP: addDON + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + bytes32[] memory nodeIds = new bytes32[](2); + nodeIds[0] = P2P_ID; + nodeIds[1] = P2P_ID_TWO; + + // SETUP: updateNodes + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + // DON requires s_basicHashedCapabilityId but we are swapping for + // s_capabilityWithConfigurationContractId + hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + uint32 capabilitiesDonId = 1; + + // Operations + changePrank(ADMIN); + s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, false, 1); + + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.CapabilityRequiredByDON.selector, + s_basicHashedCapabilityId, + capabilitiesDonId + ) + ); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + // Set node one's signer to another address + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: bytes32(abi.encodePacked(address(6666))), + hashedCapabilityIds: hashedCapabilityIds + }); + + s_CapabilitiesRegistry.updateNodes(nodes); + + // Set node two's signer to node one's signer + changePrank(NODE_OPERATOR_TWO_ADMIN); + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + hashedCapabilityIds: hashedCapabilityIds + }); + s_CapabilitiesRegistry.updateNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID_TWO); + assertEq(node.signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + } + + function test_UpdatesNodeParams() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NEW_NODE_SIGNER, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); + s_CapabilitiesRegistry.updateNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NEW_NODE_SIGNER); + assertEq(node.hashedCapabilityIds.length, 1); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.configCount, 2); + } + + function test_OwnerCanUpdateNodes() public { + changePrank(ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NEW_NODE_SIGNER, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); + s_CapabilitiesRegistry.updateNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NEW_NODE_SIGNER); + assertEq(node.hashedCapabilityIds.length, 1); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.configCount, 2); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddDONTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddDONTest.t.sol deleted file mode 100644 index f9768f7105..0000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddDONTest.t.sol +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_AddDONTest is BaseTest { - event ConfigSet(uint32 donId, uint32 configCount); - - function setUp() public override { - BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); - - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](3); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicHashedCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: capabilityIds - }); - - bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); - nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[1] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - hashedCapabilityIds: nodeTwoCapabilityIds - }); - - nodes[2] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, - p2pId: P2P_ID_THREE, - signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, - hashedCapabilityIds: capabilityIds - }); - - s_capabilityRegistry.addNodes(nodes); - - changePrank(ADMIN); - } - - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - bytes32[] memory nodes = new bytes32[](1); - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_NodeDoesNotSupportCapability() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_capabilityWithConfigurationContractId, - config: CONFIG_CAPABILITY_CONFIG - }); - vm.expectRevert( - abi.encodeWithSelector( - CapabilityRegistry.NodeDoesNotSupportCapability.selector, - P2P_ID_TWO, - s_capabilityWithConfigurationContractId - ) - ); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_CapabilityDoesNotExist() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_nonExistentHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) - ); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_FaultToleranceIsZero() public { - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = P2P_ID; - - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidFaultTolerance.selector, 0, 1)); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, 0); - } - - function test_RevertWhen_DuplicateCapabilityAdded() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - capabilityConfigs[1] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) - ); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_DeprecatedCapabilityAdded() public { - bytes32 capabilityId = s_basicHashedCapabilityId; - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = capabilityId; - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); - - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: capabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityIsDeprecated.selector, capabilityId)); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_DuplicateNodeAdded() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID; - - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.DuplicateDONNode.selector, 1, P2P_ID)); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_AddDON() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_THREE; - - CapabilityRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilityRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - capabilityConfigs[1] = CapabilityRegistry.CapabilityConfiguration({ - capabilityId: s_capabilityWithConfigurationContractId, - config: CONFIG_CAPABILITY_CONFIG - }); - - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit ConfigSet(DON_ID, 1); - vm.expectCall( - address(s_capabilityConfigurationContract), - abi.encodeWithSelector( - ICapabilityConfiguration.beforeCapabilityConfigSet.selector, - nodes, - CONFIG_CAPABILITY_CONFIG, - 1, - DON_ID - ), - 1 - ); - s_capabilityRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - - CapabilityRegistry.DONInfo memory donInfo = s_capabilityRegistry.getDON(DON_ID); - assertEq(donInfo.id, DON_ID); - assertEq(donInfo.configCount, 1); - assertEq(donInfo.isPublic, true); - assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); - assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - - (bytes memory capabilityRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_capabilityRegistry - .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); - assertEq(capabilityRegistryDONConfig, BASIC_CAPABILITY_CONFIG); - assertEq(capabilityConfigContractConfig, bytes("")); - - (bytes memory capabilityRegistryDONConfigTwo, bytes memory capabilityConfigContractConfigTwo) = s_capabilityRegistry - .getCapabilityConfigs(DON_ID, s_capabilityWithConfigurationContractId); - assertEq(capabilityRegistryDONConfigTwo, CONFIG_CAPABILITY_CONFIG); - assertEq(capabilityConfigContractConfigTwo, CONFIG_CAPABILITY_CONFIG); - - assertEq(donInfo.nodeP2PIds.length, nodes.length); - assertEq(donInfo.nodeP2PIds[0], P2P_ID); - assertEq(donInfo.nodeP2PIds[1], P2P_ID_THREE); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol deleted file mode 100644 index 6fa799bd37..0000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_AddNodeOperatorsTest is BaseTest { - event NodeOperatorAdded(uint32 indexed nodeOperatorId, address indexed admin, string name); - - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - } - - function test_RevertWhen_NodeOperatorAdminAddressZero() public { - changePrank(ADMIN); - CapabilityRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); - nodeOperators[0].admin = address(0); - vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); - s_capabilityRegistry.addNodeOperators(nodeOperators); - } - - function test_AddNodeOperators() public { - changePrank(ADMIN); - - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit NodeOperatorAdded(TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_ADMIN, NODE_OPERATOR_ONE_NAME); - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit NodeOperatorAdded(TEST_NODE_OPERATOR_TWO_ID, NODE_OPERATOR_TWO_ADMIN, NODE_OPERATOR_TWO_NAME); - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - - CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator( - TEST_NODE_OPERATOR_ONE_ID - ); - assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); - assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); - - CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator( - TEST_NODE_OPERATOR_TWO_ID - ); - assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); - assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol deleted file mode 100644 index e2dff28125..0000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilitiesTest.t.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - s_capabilityRegistry.addCapabilities(capabilities); - } - - function test_ReturnsCapabilities() public view { - (bytes32[] memory hashedCapabilityIds, CapabilityRegistry.Capability[] memory capabilities) = s_capabilityRegistry - .getCapabilities(); - - assertEq(hashedCapabilityIds.length, 2); - assertEq(hashedCapabilityIds[0], keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); - assertEq(hashedCapabilityIds[1], keccak256(abi.encode(capabilities[1].labelledName, capabilities[1].version))); - - assertEq(capabilities.length, 2); - - assertEq(capabilities[0].labelledName, "data-streams-reports"); - assertEq(capabilities[0].version, "1.0.0"); - assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); - assertEq(uint256(capabilities[0].capabilityType), uint256(CapabilityRegistry.CapabilityType.TRIGGER)); - assertEq(capabilities[0].configurationContract, address(0)); - - assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); - assertEq(capabilities[1].version, "1.0.2"); - assertEq( - uint256(capabilities[1].responseType), - uint256(CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) - ); - assertEq(uint256(capabilities[1].capabilityType), uint256(CapabilityRegistry.CapabilityType.ACTION)); - assertEq(capabilities[1].configurationContract, address(s_capabilityConfigurationContract)); - } - - function test_ExcludesDeprecatedCapabilities() public { - bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = hashedCapabilityId; - s_capabilityRegistry.deprecateCapabilities(deprecatedCapabilities); - - (bytes32[] memory hashedCapabilityIds, CapabilityRegistry.Capability[] memory capabilities) = s_capabilityRegistry - .getCapabilities(); - - assertEq(hashedCapabilityIds.length, 1); - assertEq(hashedCapabilityIds[0], keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); - - assertEq(capabilities.length, 1); - - assertEq(capabilities[0].labelledName, "read-ethereum-mainnet-gas-price"); - assertEq(capabilities[0].version, "1.0.2"); - assertEq( - uint256(capabilities[0].responseType), - uint256(CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) - ); - assertEq(capabilities[0].configurationContract, address(s_capabilityConfigurationContract)); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_TypeAndVersionTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_TypeAndVersionTest.t.sol deleted file mode 100644 index 629b4a17a5..0000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_TypeAndVersionTest.t.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; - -contract CapabilityRegistry_TypeAndVersionTest is BaseTest { - function test_TypeAndVersion() public view { - assertEq(s_capabilityRegistry.typeAndVersion(), "CapabilityRegistry 1.0.0"); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol deleted file mode 100644 index 77d180a784..0000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_UpdateNodeOperatorTest is BaseTest { - event NodeOperatorUpdated(uint32 indexed nodeOperatorId, address indexed admin, string name); - - uint32 private constant TEST_NODE_OPERATOR_ID = 1; - address private constant NEW_NODE_OPERATOR_ADMIN = address(3); - string private constant NEW_NODE_OPERATOR_NAME = "new-node-operator"; - - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - } - - function test_RevertWhen_CalledByNonAdminAndNonOwner() public { - changePrank(STRANGER); - - CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); - - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.AccessForbidden.selector, STRANGER)); - s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_RevertWhen_NodeOperatorAdminIsZeroAddress() public { - changePrank(ADMIN); - CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: address(0), name: NEW_NODE_OPERATOR_NAME}); - - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; - - vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); - s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() public { - changePrank(ADMIN); - CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); - - uint32 invalidNodeOperatorId = 10000; - uint32[] memory nodeOperatorIds = new uint32[](2); - nodeOperatorIds[0] = invalidNodeOperatorId; - vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.LengthMismatch.selector, nodeOperatorIds.length, nodeOperators.length) - ); - s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_RevertWhen_NodeOperatorDoesNotExist() public { - changePrank(ADMIN); - CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); - - uint32 invalidNodeOperatorId = 10000; - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = invalidNodeOperatorId; - vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) - ); - s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_UpdatesNodeOperator() public { - changePrank(ADMIN); - - CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); - - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; - - vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); - emit NodeOperatorUpdated(TEST_NODE_OPERATOR_ID, NEW_NODE_OPERATOR_ADMIN, NEW_NODE_OPERATOR_NAME); - s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - - CapabilityRegistry.NodeOperator memory nodeOperator = s_capabilityRegistry.getNodeOperator(TEST_NODE_OPERATOR_ID); - assertEq(nodeOperator.admin, NEW_NODE_OPERATOR_ADMIN); - assertEq(nodeOperator.name, NEW_NODE_OPERATOR_NAME); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol deleted file mode 100644 index da4e811c3e..0000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistry_UpdateNodesTest is BaseTest { - event NodeUpdated(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer); - - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - CapabilityRegistry.Capability[] memory capabilities = new CapabilityRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_capabilityRegistry.addNodeOperators(_getNodeOperators()); - s_capabilityRegistry.addCapabilities(capabilities); - - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - changePrank(NODE_OPERATOR_ONE_ADMIN); - s_capabilityRegistry.addNodes(nodes); - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - changePrank(NODE_OPERATOR_TWO_ADMIN); - s_capabilityRegistry.addNodes(nodes); - } - - function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { - changePrank(STRANGER); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.AccessForbidden.selector, STRANGER)); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_RevertWhen_NodeDoesNotExist() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: INVALID_P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_RevertWhen_P2PIDEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: bytes32(""), - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.NodeDoesNotExist.selector, bytes32(""))); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_RevertWhen_SignerAddressEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: bytes32(""), - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(CapabilityRegistry.InvalidNodeSigner.selector); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_RevertWhen_UpdatingNodeWithoutCapabilities() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](0); - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_RevertWhen_AddingNodeWithInvalidCapability() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_capabilityRegistry.updateNodes(nodes); - } - - function test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - // Set node one's signer to another address - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: bytes32(abi.encodePacked(address(6666))), - hashedCapabilityIds: hashedCapabilityIds - }); - - s_capabilityRegistry.updateNodes(nodes); - - // Set node two's signer to node one's signer - changePrank(NODE_OPERATOR_TWO_ADMIN); - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - hashedCapabilityIds: hashedCapabilityIds - }); - s_capabilityRegistry.updateNodes(nodes); - - (CapabilityRegistry.NodeInfo memory node, ) = s_capabilityRegistry.getNode(P2P_ID_TWO); - assertEq(node.signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - } - - function test_UpdatesNodeInfo() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NEW_NODE_SIGNER, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectEmit(address(s_capabilityRegistry)); - emit NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); - s_capabilityRegistry.updateNodes(nodes); - - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.signer, NEW_NODE_SIGNER); - assertEq(node.hashedCapabilityIds.length, 1); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(configCount, 2); - } - - function test_OwnerCanUpdateNodes() public { - changePrank(ADMIN); - - CapabilityRegistry.NodeInfo[] memory nodes = new CapabilityRegistry.NodeInfo[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilityRegistry.NodeInfo({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NEW_NODE_SIGNER, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectEmit(address(s_capabilityRegistry)); - emit NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); - s_capabilityRegistry.updateNodes(nodes); - - (CapabilityRegistry.NodeInfo memory node, uint32 configCount) = s_capabilityRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.signer, NEW_NODE_SIGNER); - assertEq(node.hashedCapabilityIds.length, 1); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(configCount, 2); - } -} diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol index 9b13bd91f5..23c80eea9f 100644 --- a/contracts/src/v0.8/keystone/test/Constants.t.sol +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -23,7 +23,7 @@ contract Constants { bytes32 internal constant NODE_OPERATOR_THREE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(5555))); bytes32 internal constant P2P_ID_THREE = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a06"; - uint32 internal constant F_VALUE = 1; + uint8 internal constant F_VALUE = 1; uint32 internal constant DON_ID = 1; uint32 internal constant DON_ID_TWO = 2; diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol index fc5c3a160d..3b3c406078 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol @@ -20,11 +20,14 @@ contract BaseTest is Test { Signer[MAX_ORACLES] internal s_signers; KeystoneForwarder internal s_forwarder; + KeystoneForwarder internal s_router; Receiver internal s_receiver; function setUp() public virtual { vm.startPrank(ADMIN); + s_router = new KeystoneForwarder(); s_forwarder = new KeystoneForwarder(); + s_router.addForwarder(address(s_forwarder)); s_receiver = new Receiver(); uint256 seed = 0; diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol index f68917ba85..ccb398fac5 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol @@ -2,11 +2,17 @@ pragma solidity ^0.8.19; import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; import {KeystoneForwarder} from "../KeystoneForwarder.sol"; contract KeystoneForwarder_ReportTest is BaseTest { event MessageReceived(bytes metadata, bytes[] mercuryReports); - event ReportProcessed(address indexed receiver, bytes32 indexed workflowExecutionId, bool result); + event ReportProcessed( + address indexed receiver, + bytes32 indexed workflowExecutionId, + bytes2 indexed reportId, + bool result + ); uint8 internal version = 1; uint32 internal timestamp = 0; @@ -28,6 +34,7 @@ contract KeystoneForwarder_ReportTest is BaseTest { BaseTest.setUp(); s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); + s_router.addForwarder(address(s_forwarder)); mercuryReports[0] = hex"010203"; mercuryReports[1] = hex"aabbccdd"; @@ -57,7 +64,8 @@ contract KeystoneForwarder_ReportTest is BaseTest { rawReports ); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, invalidDONId, CONFIG_VERSION)); + uint64 configId = (uint64(invalidDONId) << 32) | CONFIG_VERSION; + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); } @@ -75,7 +83,8 @@ contract KeystoneForwarder_ReportTest is BaseTest { rawReports ); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, DON_ID, CONFIG_VERSION + 1)); + uint64 configId = (uint64(DON_ID) << 32) | (CONFIG_VERSION + 1); + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); } @@ -132,11 +141,11 @@ contract KeystoneForwarder_ReportTest is BaseTest { s_forwarder.report(address(s_receiver), report, reportContext, signatures); } - function test_RevertWhen_AlreadyProcessed() public { + function test_RevertWhen_AlreadyAttempted() public { s_forwarder.report(address(s_receiver), report, reportContext, signatures); - bytes32 combinedId = keccak256(bytes.concat(bytes20(uint160(address(s_receiver))), executionId, reportId)); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.AlreadyProcessed.selector, combinedId)); + bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); + vm.expectRevert(abi.encodeWithSelector(IRouter.AlreadyAttempted.selector, transmissionId)); s_forwarder.report(address(s_receiver), report, reportContext, signatures); } @@ -145,13 +154,54 @@ contract KeystoneForwarder_ReportTest is BaseTest { emit MessageReceived(metadata, mercuryReports); vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), executionId, true); + emit ReportProcessed(address(s_receiver), executionId, reportId, true); s_forwarder.report(address(s_receiver), report, reportContext, signatures); - // validate transmitter was recorded - address transmitter = s_forwarder.getTransmitter(address(s_receiver), executionId, reportId); - assertEq(transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq( + s_forwarder.getTransmitter(address(s_receiver), executionId, reportId), + TRANSMITTER, + "transmitter mismatch" + ); + assertEq( + uint8(s_forwarder.getTransmissionState(address(s_receiver), executionId, reportId)), + uint8(IRouter.TransmissionState.SUCCEEDED), + "TransmissionState mismatch" + ); + } + + function test_Report_FailedDeliveryWhenReceiverNotContract() public { + // Receiver is not a contract + address receiver = address(404); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(receiver, executionId, reportId, false); + + s_forwarder.report(receiver, report, reportContext, signatures); + + assertEq(s_forwarder.getTransmitter(receiver, executionId, reportId), TRANSMITTER, "transmitter mismatch"); + assertEq( + uint8(s_forwarder.getTransmissionState(receiver, executionId, reportId)), + uint8(IRouter.TransmissionState.FAILED), + "TransmissionState mismatch" + ); + } + + function test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() public { + // Receiver is a contract but doesn't implement the required interface + address receiver = address(s_forwarder); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(receiver, executionId, reportId, false); + + s_forwarder.report(receiver, report, reportContext, signatures); + + assertEq(s_forwarder.getTransmitter(receiver, executionId, reportId), TRANSMITTER, "transmitter mismatch"); + assertEq( + uint8(s_forwarder.getTransmissionState(receiver, executionId, reportId)), + uint8(IRouter.TransmissionState.FAILED), + "TransmissionState mismatch" + ); } function test_Report_ConfigVersion() public { @@ -165,7 +215,7 @@ contract KeystoneForwarder_ReportTest is BaseTest { emit MessageReceived(metadata, mercuryReports); vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), executionId, true); + emit ReportProcessed(address(s_receiver), executionId, reportId, true); vm.prank(TRANSMITTER); s_forwarder.report(address(s_receiver), report, reportContext, signatures); @@ -174,7 +224,8 @@ contract KeystoneForwarder_ReportTest is BaseTest { vm.prank(ADMIN); s_forwarder.clearConfig(DON_ID, CONFIG_VERSION); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, DON_ID, CONFIG_VERSION)); + uint64 configId = (uint64(DON_ID) << 32) | CONFIG_VERSION; + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); vm.prank(TRANSMITTER); s_forwarder.report(address(s_receiver), report, reportContext, signatures); @@ -197,7 +248,7 @@ contract KeystoneForwarder_ReportTest is BaseTest { emit MessageReceived(newMetadata, mercuryReports); vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), newExecutionId, true); + emit ReportProcessed(address(s_receiver), newExecutionId, reportId, true); vm.prank(TRANSMITTER); s_forwarder.report(address(s_receiver), newReport, reportContext, newSignatures); diff --git a/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol index 1d8d7572e0..8aad376649 100644 --- a/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol +++ b/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol @@ -5,6 +5,6 @@ import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; contract KeystoneForwarder_TypeAndVersionTest is BaseTest { function test_TypeAndVersion() public view { - assertEq(s_forwarder.typeAndVersion(), "KeystoneForwarder 1.0.0"); + assertEq(s_forwarder.typeAndVersion(), "Forwarder and Router 1.0.0"); } } diff --git a/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol b/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol new file mode 100644 index 0000000000..c126f7ce31 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {IReceiver} from "../interfaces/IReceiver.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; +import {KeystoneForwarder} from "../KeystoneForwarder.sol"; + +contract KeystoneRouter_SetConfigTest is Test { + address internal ADMIN = address(1); + address internal constant STRANGER = address(2); + address internal constant FORWARDER = address(99); + address internal constant TRANSMITTER = address(50); + address internal constant RECEIVER = address(51); + + bytes internal metadata = hex"01020304"; + bytes internal report = hex"9998"; + bytes32 internal id = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; + + KeystoneForwarder internal s_router; + + function setUp() public virtual { + vm.prank(ADMIN); + s_router = new KeystoneForwarder(); + } + + function test_AddForwarder_RevertWhen_NotOwner() public { + vm.prank(STRANGER); + vm.expectRevert(); + s_router.addForwarder(FORWARDER); + } + + function test_RemoveForwarder_RevertWhen_NotOwner() public { + vm.prank(STRANGER); + vm.expectRevert(); + s_router.removeForwarder(FORWARDER); + } + + function test_Route_RevertWhen_UnauthorizedForwarder() public { + vm.prank(STRANGER); + vm.expectRevert(IRouter.UnauthorizedForwarder.selector); + s_router.route(id, TRANSMITTER, RECEIVER, metadata, report); + } + + function test_Route_Success() public { + assertEq(s_router.isForwarder(FORWARDER), false); + + vm.prank(ADMIN); + s_router.addForwarder(FORWARDER); + assertEq(s_router.isForwarder(FORWARDER), true); + + vm.prank(FORWARDER); + vm.mockCall(RECEIVER, abi.encodeCall(IReceiver.onReport, (metadata, report)), abi.encode()); + vm.expectCall(RECEIVER, abi.encodeCall(IReceiver.onReport, (metadata, report))); + s_router.route(id, TRANSMITTER, RECEIVER, metadata, report); + } +} diff --git a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol index 2dd86fdf6d..c2a916c87e 100644 --- a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol +++ b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.24; import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; import {ERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol"; diff --git a/contracts/src/v0.8/vendor/forge-std/src/Base.sol b/contracts/src/v0.8/vendor/forge-std/src/Base.sol new file mode 100644 index 0000000000..851ac0cd2b --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/Base.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {StdStorage} from "./StdStorage.sol"; +import {Vm, VmSafe} from "./Vm.sol"; + +abstract contract CommonBase { + // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. + address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); + // console.sol and console2.sol work by executing a staticcall to this address. + address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; + // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. + address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. + address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller")))); + // Address of the test contract, deployed by the DEFAULT_SENDER. + address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; + // Deterministic deployment address of the Multicall3 contract. + address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; + // The order of the secp256k1 curve. + uint256 internal constant SECP256K1_ORDER = + 115792089237316195423570985008687907852837564279074904382605163141518161494337; + + uint256 internal constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + Vm internal constant vm = Vm(VM_ADDRESS); + StdStorage internal stdstore; +} + +abstract contract TestBase is CommonBase {} + +abstract contract ScriptBase is CommonBase { + VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/Script.sol b/contracts/src/v0.8/vendor/forge-std/src/Script.sol new file mode 100644 index 0000000000..94e75f6cbc --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/Script.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +// 💬 ABOUT +// Forge Std's default Script. + +// 🧩 MODULES +import {console} from "./console.sol"; +import {console2} from "./console2.sol"; +import {safeconsole} from "./safeconsole.sol"; +import {StdChains} from "./StdChains.sol"; +import {StdCheatsSafe} from "./StdCheats.sol"; +import {stdJson} from "./StdJson.sol"; +import {stdMath} from "./StdMath.sol"; +import {StdStorage, stdStorageSafe} from "./StdStorage.sol"; +import {StdStyle} from "./StdStyle.sol"; +import {StdUtils} from "./StdUtils.sol"; +import {VmSafe} from "./Vm.sol"; + +// 📦 BOILERPLATE +import {ScriptBase} from "./Base.sol"; + +// ⭐️ SCRIPT +abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils { + // Note: IS_SCRIPT() must return true. + bool public IS_SCRIPT = true; +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol b/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol new file mode 100644 index 0000000000..857ecd5704 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol @@ -0,0 +1,669 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +import {Vm} from "./Vm.sol"; + +abstract contract StdAssertions { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + event log(string); + event logs(bytes); + + event log_address(address); + event log_bytes32(bytes32); + event log_int(int256); + event log_uint(uint256); + event log_bytes(bytes); + event log_string(string); + + event log_named_address(string key, address val); + event log_named_bytes32(string key, bytes32 val); + event log_named_decimal_int(string key, int256 val, uint256 decimals); + event log_named_decimal_uint(string key, uint256 val, uint256 decimals); + event log_named_int(string key, int256 val); + event log_named_uint(string key, uint256 val); + event log_named_bytes(string key, bytes val); + event log_named_string(string key, string val); + + event log_array(uint256[] val); + event log_array(int256[] val); + event log_array(address[] val); + event log_named_array(string key, uint256[] val); + event log_named_array(string key, int256[] val); + event log_named_array(string key, address[] val); + + bool private _failed; + + function failed() public view returns (bool) { + if (_failed) { + return _failed; + } else { + return vm.load(address(vm), bytes32("failed")) != bytes32(0); + } + } + + function fail() internal virtual { + vm.store(address(vm), bytes32("failed"), bytes32(uint256(1))); + _failed = true; + } + + function assertTrue(bool data) internal pure virtual { + vm.assertTrue(data); + } + + function assertTrue(bool data, string memory err) internal pure virtual { + vm.assertTrue(data, err); + } + + function assertFalse(bool data) internal pure virtual { + vm.assertFalse(data); + } + + function assertFalse(bool data, string memory err) internal pure virtual { + vm.assertFalse(data, err); + } + + function assertEq(bool left, bool right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bool left, bool right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(uint256 left, uint256 right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertEqDecimal(left, right, decimals); + } + + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertEqDecimal(left, right, decimals, err); + } + + function assertEq(int256 left, int256 right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertEqDecimal(left, right, decimals); + } + + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertEqDecimal(left, right, decimals, err); + } + + function assertEq(address left, address right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(address left, address right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes32 left, bytes32 right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq32(bytes32 left, bytes32 right) internal pure virtual { + assertEq(left, right); + } + + function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { + assertEq(left, right, err); + } + + function assertEq(string memory left, string memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(string memory left, string memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes memory left, bytes memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bool[] memory left, bool[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(int256[] memory left, int256[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(address[] memory left, address[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(string[] memory left, string[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + // Legacy helper + function assertEqUint(uint256 left, uint256 right) internal pure virtual { + assertEq(left, right); + } + + function assertNotEq(bool left, bool right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bool left, bool right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(uint256 left, uint256 right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals); + } + + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) + internal + pure + virtual + { + vm.assertNotEqDecimal(left, right, decimals, err); + } + + function assertNotEq(int256 left, int256 right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals); + } + + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals, err); + } + + function assertNotEq(address left, address right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(address left, address right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes32 left, bytes32 right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual { + assertNotEq(left, right); + } + + function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { + assertNotEq(left, right, err); + } + + function assertNotEq(string memory left, string memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes memory left, bytes memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(address[] memory left, address[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(string[] memory left, string[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertLt(uint256 left, uint256 right) internal pure virtual { + vm.assertLt(left, right); + } + + function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertLt(left, right, err); + } + + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertLtDecimal(left, right, decimals); + } + + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLtDecimal(left, right, decimals, err); + } + + function assertLt(int256 left, int256 right) internal pure virtual { + vm.assertLt(left, right); + } + + function assertLt(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertLt(left, right, err); + } + + function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertLtDecimal(left, right, decimals); + } + + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLtDecimal(left, right, decimals, err); + } + + function assertGt(uint256 left, uint256 right) internal pure virtual { + vm.assertGt(left, right); + } + + function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertGt(left, right, err); + } + + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertGtDecimal(left, right, decimals); + } + + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGtDecimal(left, right, decimals, err); + } + + function assertGt(int256 left, int256 right) internal pure virtual { + vm.assertGt(left, right); + } + + function assertGt(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertGt(left, right, err); + } + + function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertGtDecimal(left, right, decimals); + } + + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGtDecimal(left, right, decimals, err); + } + + function assertLe(uint256 left, uint256 right) internal pure virtual { + vm.assertLe(left, right); + } + + function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertLe(left, right, err); + } + + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertLeDecimal(left, right, decimals); + } + + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLeDecimal(left, right, decimals, err); + } + + function assertLe(int256 left, int256 right) internal pure virtual { + vm.assertLe(left, right); + } + + function assertLe(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertLe(left, right, err); + } + + function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertLeDecimal(left, right, decimals); + } + + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLeDecimal(left, right, decimals, err); + } + + function assertGe(uint256 left, uint256 right) internal pure virtual { + vm.assertGe(left, right); + } + + function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertGe(left, right, err); + } + + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertGeDecimal(left, right, decimals); + } + + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGeDecimal(left, right, decimals, err); + } + + function assertGe(int256 left, int256 right) internal pure virtual { + vm.assertGe(left, right); + } + + function assertGe(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertGe(left, right, err); + } + + function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertGeDecimal(left, right, decimals); + } + + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGeDecimal(left, right, decimals, err); + } + + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta); + } + + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) + internal + pure + virtual + { + vm.assertApproxEqAbs(left, right, maxDelta, err); + } + + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); + } + + function assertApproxEqAbsDecimal( + uint256 left, + uint256 right, + uint256 maxDelta, + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); + } + + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta); + } + + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta, err); + } + + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); + } + + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); + } + + function assertApproxEqRel( + uint256 left, + uint256 right, + uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% + ) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta); + } + + function assertApproxEqRel( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + string memory err + ) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta, err); + } + + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); + } + + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); + } + + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta); + } + + function assertApproxEqRel( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + string memory err + ) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta, err); + } + + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); + } + + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); + } + + // Inherited from DSTest, not used but kept for backwards-compatibility + function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) { + return keccak256(left) == keccak256(right); + } + + function assertEq0(bytes memory left, bytes memory right) internal pure virtual { + assertEq(left, right); + } + + function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { + assertEq(left, right, err); + } + + function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual { + assertNotEq(left, right); + } + + function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { + assertNotEq(left, right, err); + } + + function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual { + assertEqCall(target, callDataA, target, callDataB, true); + } + + function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) + internal + virtual + { + assertEqCall(targetA, callDataA, targetB, callDataB, true); + } + + function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) + internal + virtual + { + assertEqCall(target, callDataA, target, callDataB, strictRevertData); + } + + function assertEqCall( + address targetA, + bytes memory callDataA, + address targetB, + bytes memory callDataB, + bool strictRevertData + ) internal virtual { + (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); + (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); + + if (successA && successB) { + assertEq(returnDataA, returnDataB, "Call return data does not match"); + } + + if (!successA && !successB && strictRevertData) { + assertEq(returnDataA, returnDataB, "Call revert data does not match"); + } + + if (!successA && successB) { + emit log("Error: Calls were not equal"); + emit log_named_bytes(" Left call revert data", returnDataA); + emit log_named_bytes(" Right call return data", returnDataB); + revert("assertion failed"); + } + + if (successA && !successB) { + emit log("Error: Calls were not equal"); + emit log_named_bytes(" Left call return data", returnDataA); + emit log_named_bytes(" Right call revert data", returnDataB); + revert("assertion failed"); + } + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol b/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol new file mode 100644 index 0000000000..5815bd69cf --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {VmSafe} from "./Vm.sol"; + +/** + * StdChains provides information about EVM compatible chains that can be used in scripts/tests. + * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are + * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of + * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the + * alias used in this contract, which can be found as the first argument to the + * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. + * + * There are two main ways to use this contract: + * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or + * `setChain(string memory chainAlias, Chain memory chain)` + * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. + * + * The first time either of those are used, chains are initialized with the default set of RPC URLs. + * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in + * `defaultRpcUrls`. + * + * The `setChain` function is straightforward, and it simply saves off the given chain data. + * + * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say + * we want to retrieve the RPC URL for `mainnet`: + * - If you have specified data with `setChain`, it will return that. + * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it + * is valid (e.g. a URL is specified, or an environment variable is given and exists). + * - If neither of the above conditions is met, the default data is returned. + * + * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. + */ +abstract contract StdChains { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + bool private stdChainsInitialized; + + struct ChainData { + string name; + uint256 chainId; + string rpcUrl; + } + + struct Chain { + // The chain name. + string name; + // The chain's Chain ID. + uint256 chainId; + // The chain's alias. (i.e. what gets specified in `foundry.toml`). + string chainAlias; + // A default RPC endpoint for this chain. + // NOTE: This default RPC URL is included for convenience to facilitate quick tests and + // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy + // usage as you will be throttled and this is a disservice to others who need this endpoint. + string rpcUrl; + } + + // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. + mapping(string => Chain) private chains; + // Maps from the chain's alias to it's default RPC URL. + mapping(string => string) private defaultRpcUrls; + // Maps from a chain ID to it's alias. + mapping(uint256 => string) private idToAlias; + + bool private fallbackToDefaultRpcUrls = true; + + // The RPC URL will be fetched from config or defaultRpcUrls if possible. + function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { + require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); + + initializeStdChains(); + chain = chains[chainAlias]; + require( + chain.chainId != 0, + string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) + ); + + chain = getChainWithUpdatedRpcUrl(chainAlias, chain); + } + + function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { + require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); + initializeStdChains(); + string memory chainAlias = idToAlias[chainId]; + + chain = chains[chainAlias]; + + require( + chain.chainId != 0, + string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) + ); + + chain = getChainWithUpdatedRpcUrl(chainAlias, chain); + } + + // set chain info, with priority to argument's rpcUrl field. + function setChain(string memory chainAlias, ChainData memory chain) internal virtual { + require( + bytes(chainAlias).length != 0, + "StdChains setChain(string,ChainData): Chain alias cannot be the empty string." + ); + + require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); + + initializeStdChains(); + string memory foundAlias = idToAlias[chain.chainId]; + + require( + bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), + string( + abi.encodePacked( + "StdChains setChain(string,ChainData): Chain ID ", + vm.toString(chain.chainId), + " already used by \"", + foundAlias, + "\"." + ) + ) + ); + + uint256 oldChainId = chains[chainAlias].chainId; + delete idToAlias[oldChainId]; + + chains[chainAlias] = + Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); + idToAlias[chain.chainId] = chainAlias; + } + + // set chain info, with priority to argument's rpcUrl field. + function setChain(string memory chainAlias, Chain memory chain) internal virtual { + setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); + } + + function _toUpper(string memory str) private pure returns (string memory) { + bytes memory strb = bytes(str); + bytes memory copy = new bytes(strb.length); + for (uint256 i = 0; i < strb.length; i++) { + bytes1 b = strb[i]; + if (b >= 0x61 && b <= 0x7A) { + copy[i] = bytes1(uint8(b) - 32); + } else { + copy[i] = b; + } + } + return string(copy); + } + + // lookup rpcUrl, in descending order of priority: + // current -> config (foundry.toml) -> environment variable -> default + function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) + private + view + returns (Chain memory) + { + if (bytes(chain.rpcUrl).length == 0) { + try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) { + chain.rpcUrl = configRpcUrl; + } catch (bytes memory err) { + string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); + if (fallbackToDefaultRpcUrls) { + chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); + } else { + chain.rpcUrl = vm.envString(envName); + } + // Distinguish 'not found' from 'cannot read' + // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions + bytes memory oldNotFoundError = + abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias))); + bytes memory newNotFoundError = abi.encodeWithSignature( + "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias)) + ); + bytes32 errHash = keccak256(err); + if ( + (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) + || bytes(chain.rpcUrl).length == 0 + ) { + /// @solidity memory-safe-assembly + assembly { + revert(add(32, err), mload(err)) + } + } + } + } + return chain; + } + + function setFallbackToDefaultRpcUrls(bool useDefault) internal { + fallbackToDefaultRpcUrls = useDefault; + } + + function initializeStdChains() private { + if (stdChainsInitialized) return; + + stdChainsInitialized = true; + + // If adding an RPC here, make sure to test the default RPC URL in `testRpcs` + setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); + setChainWithDefaultRpcUrl( + "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP") + ); + setChainWithDefaultRpcUrl( + "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") + ); + setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); + setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); + setChainWithDefaultRpcUrl( + "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io") + ); + setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); + setChainWithDefaultRpcUrl( + "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc") + ); + setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); + setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); + setChainWithDefaultRpcUrl( + "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology") + ); + setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); + setChainWithDefaultRpcUrl( + "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") + ); + setChainWithDefaultRpcUrl( + "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") + ); + setChainWithDefaultRpcUrl( + "bnb_smart_chain_testnet", + ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") + ); + setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); + setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); + setChainWithDefaultRpcUrl( + "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") + ); + setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); + setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); + setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); + setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); + setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); + } + + // set chain info, with priority to chainAlias' rpc url in foundry.toml + function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { + string memory rpcUrl = chain.rpcUrl; + defaultRpcUrls[chainAlias] = rpcUrl; + chain.rpcUrl = ""; + setChain(chainAlias, chain); + chain.rpcUrl = rpcUrl; // restore argument + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol b/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol new file mode 100644 index 0000000000..f2933139cc --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol @@ -0,0 +1,817 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {StdStorage, stdStorage} from "./StdStorage.sol"; +import {console2} from "./console2.sol"; +import {Vm} from "./Vm.sol"; + +abstract contract StdCheatsSafe { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + uint256 private constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + bool private gasMeteringOff; + + // Data structures to parse Transaction objects from the broadcast artifact + // that conform to EIP1559. The Raw structs is what is parsed from the JSON + // and then converted to the one that is used by the user for better UX. + + struct RawTx1559 { + string[] arguments; + address contractAddress; + string contractName; + // json value name = function + string functionSig; + bytes32 hash; + // json value name = tx + RawTx1559Detail txDetail; + // json value name = type + string opcode; + } + + struct RawTx1559Detail { + AccessList[] accessList; + bytes data; + address from; + bytes gas; + bytes nonce; + address to; + bytes txType; + bytes value; + } + + struct Tx1559 { + string[] arguments; + address contractAddress; + string contractName; + string functionSig; + bytes32 hash; + Tx1559Detail txDetail; + string opcode; + } + + struct Tx1559Detail { + AccessList[] accessList; + bytes data; + address from; + uint256 gas; + uint256 nonce; + address to; + uint256 txType; + uint256 value; + } + + // Data structures to parse Transaction objects from the broadcast artifact + // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON + // and then converted to the one that is used by the user for better UX. + + struct TxLegacy { + string[] arguments; + address contractAddress; + string contractName; + string functionSig; + string hash; + string opcode; + TxDetailLegacy transaction; + } + + struct TxDetailLegacy { + AccessList[] accessList; + uint256 chainId; + bytes data; + address from; + uint256 gas; + uint256 gasPrice; + bytes32 hash; + uint256 nonce; + bytes1 opcode; + bytes32 r; + bytes32 s; + uint256 txType; + address to; + uint8 v; + uint256 value; + } + + struct AccessList { + address accessAddress; + bytes32[] storageKeys; + } + + // Data structures to parse Receipt objects from the broadcast artifact. + // The Raw structs is what is parsed from the JSON + // and then converted to the one that is used by the user for better UX. + + struct RawReceipt { + bytes32 blockHash; + bytes blockNumber; + address contractAddress; + bytes cumulativeGasUsed; + bytes effectiveGasPrice; + address from; + bytes gasUsed; + RawReceiptLog[] logs; + bytes logsBloom; + bytes status; + address to; + bytes32 transactionHash; + bytes transactionIndex; + } + + struct Receipt { + bytes32 blockHash; + uint256 blockNumber; + address contractAddress; + uint256 cumulativeGasUsed; + uint256 effectiveGasPrice; + address from; + uint256 gasUsed; + ReceiptLog[] logs; + bytes logsBloom; + uint256 status; + address to; + bytes32 transactionHash; + uint256 transactionIndex; + } + + // Data structures to parse the entire broadcast artifact, assuming the + // transactions conform to EIP1559. + + struct EIP1559ScriptArtifact { + string[] libraries; + string path; + string[] pending; + Receipt[] receipts; + uint256 timestamp; + Tx1559[] transactions; + TxReturn[] txReturns; + } + + struct RawEIP1559ScriptArtifact { + string[] libraries; + string path; + string[] pending; + RawReceipt[] receipts; + TxReturn[] txReturns; + uint256 timestamp; + RawTx1559[] transactions; + } + + struct RawReceiptLog { + // json value = address + address logAddress; + bytes32 blockHash; + bytes blockNumber; + bytes data; + bytes logIndex; + bool removed; + bytes32[] topics; + bytes32 transactionHash; + bytes transactionIndex; + bytes transactionLogIndex; + } + + struct ReceiptLog { + // json value = address + address logAddress; + bytes32 blockHash; + uint256 blockNumber; + bytes data; + uint256 logIndex; + bytes32[] topics; + uint256 transactionIndex; + uint256 transactionLogIndex; + bool removed; + } + + struct TxReturn { + string internalType; + string value; + } + + struct Account { + address addr; + uint256 key; + } + + enum AddressType { + Payable, + NonPayable, + ZeroAddress, + Precompile, + ForgeAddress + } + + // Checks that `addr` is not blacklisted by token contracts that have a blacklist. + function assumeNotBlacklisted(address token, address addr) internal view virtual { + // Nothing to check if `token` is not a contract. + uint256 tokenCodeSize; + assembly { + tokenCodeSize := extcodesize(token) + } + require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); + + bool success; + bytes memory returnData; + + // 4-byte selector for `isBlacklisted(address)`, used by USDC. + (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr)); + vm.assume(!success || abi.decode(returnData, (bool)) == false); + + // 4-byte selector for `isBlackListed(address)`, used by USDT. + (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr)); + vm.assume(!success || abi.decode(returnData, (bool)) == false); + } + + // Checks that `addr` is not blacklisted by token contracts that have a blacklist. + // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for + // backwards compatibility, since this name was used in the original PR which has already has + // a release. This function can be removed in a future release once we want a breaking change. + function assumeNoBlacklisted(address token, address addr) internal view virtual { + assumeNotBlacklisted(token, addr); + } + + function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { + if (addressType == AddressType.Payable) { + assumeNotPayable(addr); + } else if (addressType == AddressType.NonPayable) { + assumePayable(addr); + } else if (addressType == AddressType.ZeroAddress) { + assumeNotZeroAddress(addr); + } else if (addressType == AddressType.Precompile) { + assumeNotPrecompile(addr); + } else if (addressType == AddressType.ForgeAddress) { + assumeNotForgeAddress(addr); + } + } + + function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { + assumeAddressIsNot(addr, addressType1); + assumeAddressIsNot(addr, addressType2); + } + + function assumeAddressIsNot( + address addr, + AddressType addressType1, + AddressType addressType2, + AddressType addressType3 + ) internal virtual { + assumeAddressIsNot(addr, addressType1); + assumeAddressIsNot(addr, addressType2); + assumeAddressIsNot(addr, addressType3); + } + + function assumeAddressIsNot( + address addr, + AddressType addressType1, + AddressType addressType2, + AddressType addressType3, + AddressType addressType4 + ) internal virtual { + assumeAddressIsNot(addr, addressType1); + assumeAddressIsNot(addr, addressType2); + assumeAddressIsNot(addr, addressType3); + assumeAddressIsNot(addr, addressType4); + } + + // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to + // `addr` and checking the `success` return value. + // NOTE: This function may result in state changes depending on the fallback/receive logic + // implemented by `addr`, which should be taken into account when this function is used. + function _isPayable(address addr) private returns (bool) { + require( + addr.balance < UINT256_MAX, + "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" + ); + uint256 origBalanceTest = address(this).balance; + uint256 origBalanceAddr = address(addr).balance; + + vm.deal(address(this), 1); + (bool success,) = payable(addr).call{value: 1}(""); + + // reset balances + vm.deal(address(this), origBalanceTest); + vm.deal(addr, origBalanceAddr); + + return success; + } + + // NOTE: This function may result in state changes depending on the fallback/receive logic + // implemented by `addr`, which should be taken into account when this function is used. See the + // `_isPayable` method for more information. + function assumePayable(address addr) internal virtual { + vm.assume(_isPayable(addr)); + } + + function assumeNotPayable(address addr) internal virtual { + vm.assume(!_isPayable(addr)); + } + + function assumeNotZeroAddress(address addr) internal pure virtual { + vm.assume(addr != address(0)); + } + + function assumeNotPrecompile(address addr) internal pure virtual { + assumeNotPrecompile(addr, _pureChainId()); + } + + function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { + // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific + // address), but the same rationale for excluding them applies so we include those too. + + // These should be present on all EVM-compatible chains. + vm.assume(addr < address(0x1) || addr > address(0x9)); + + // forgefmt: disable-start + if (chainId == 10 || chainId == 420) { + // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 + vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); + } else if (chainId == 42161 || chainId == 421613) { + // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains + vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068)); + } else if (chainId == 43114 || chainId == 43113) { + // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59 + vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff)); + vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF)); + vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff)); + } + // forgefmt: disable-end + } + + function assumeNotForgeAddress(address addr) internal pure virtual { + // vm, console, and Create2Deployer addresses + vm.assume( + addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67 + && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C + ); + } + + function readEIP1559ScriptArtifact(string memory path) + internal + view + virtual + returns (EIP1559ScriptArtifact memory) + { + string memory data = vm.readFile(path); + bytes memory parsedData = vm.parseJson(data); + RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact)); + EIP1559ScriptArtifact memory artifact; + artifact.libraries = rawArtifact.libraries; + artifact.path = rawArtifact.path; + artifact.timestamp = rawArtifact.timestamp; + artifact.pending = rawArtifact.pending; + artifact.txReturns = rawArtifact.txReturns; + artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts); + artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions); + return artifact; + } + + function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { + Tx1559[] memory txs = new Tx1559[](rawTxs.length); + for (uint256 i; i < rawTxs.length; i++) { + txs[i] = rawToConvertedEIPTx1559(rawTxs[i]); + } + return txs; + } + + function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { + Tx1559 memory transaction; + transaction.arguments = rawTx.arguments; + transaction.contractName = rawTx.contractName; + transaction.functionSig = rawTx.functionSig; + transaction.hash = rawTx.hash; + transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail); + transaction.opcode = rawTx.opcode; + return transaction; + } + + function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) + internal + pure + virtual + returns (Tx1559Detail memory) + { + Tx1559Detail memory txDetail; + txDetail.data = rawDetail.data; + txDetail.from = rawDetail.from; + txDetail.to = rawDetail.to; + txDetail.nonce = _bytesToUint(rawDetail.nonce); + txDetail.txType = _bytesToUint(rawDetail.txType); + txDetail.value = _bytesToUint(rawDetail.value); + txDetail.gas = _bytesToUint(rawDetail.gas); + txDetail.accessList = rawDetail.accessList; + return txDetail; + } + + function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { + string memory deployData = vm.readFile(path); + bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); + RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[])); + return rawToConvertedEIPTx1559s(rawTxs); + } + + function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { + string memory deployData = vm.readFile(path); + string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); + bytes memory parsedDeployData = vm.parseJson(deployData, key); + RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559)); + return rawToConvertedEIPTx1559(rawTx); + } + + // Analogous to readTransactions, but for receipts. + function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { + string memory deployData = vm.readFile(path); + bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); + RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[])); + return rawToConvertedReceipts(rawReceipts); + } + + function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { + string memory deployData = vm.readFile(path); + string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); + bytes memory parsedDeployData = vm.parseJson(deployData, key); + RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt)); + return rawToConvertedReceipt(rawReceipt); + } + + function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { + Receipt[] memory receipts = new Receipt[](rawReceipts.length); + for (uint256 i; i < rawReceipts.length; i++) { + receipts[i] = rawToConvertedReceipt(rawReceipts[i]); + } + return receipts; + } + + function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { + Receipt memory receipt; + receipt.blockHash = rawReceipt.blockHash; + receipt.to = rawReceipt.to; + receipt.from = rawReceipt.from; + receipt.contractAddress = rawReceipt.contractAddress; + receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice); + receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed); + receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed); + receipt.status = _bytesToUint(rawReceipt.status); + receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex); + receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber); + receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs); + receipt.logsBloom = rawReceipt.logsBloom; + receipt.transactionHash = rawReceipt.transactionHash; + return receipt; + } + + function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) + internal + pure + virtual + returns (ReceiptLog[] memory) + { + ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length); + for (uint256 i; i < rawLogs.length; i++) { + logs[i].logAddress = rawLogs[i].logAddress; + logs[i].blockHash = rawLogs[i].blockHash; + logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber); + logs[i].data = rawLogs[i].data; + logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex); + logs[i].topics = rawLogs[i].topics; + logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex); + logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex); + logs[i].removed = rawLogs[i].removed; + } + return logs; + } + + // Deploy a contract by fetching the contract bytecode from + // the artifacts directory + // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` + function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { + bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); + /// @solidity memory-safe-assembly + assembly { + addr := create(0, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); + } + + function deployCode(string memory what) internal virtual returns (address addr) { + bytes memory bytecode = vm.getCode(what); + /// @solidity memory-safe-assembly + assembly { + addr := create(0, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); + } + + /// @dev deploy contract with value on construction + function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { + bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); + /// @solidity memory-safe-assembly + assembly { + addr := create(val, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); + } + + function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { + bytes memory bytecode = vm.getCode(what); + /// @solidity memory-safe-assembly + assembly { + addr := create(val, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); + } + + // creates a labeled address and the corresponding private key + function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { + privateKey = uint256(keccak256(abi.encodePacked(name))); + addr = vm.addr(privateKey); + vm.label(addr, name); + } + + // creates a labeled address + function makeAddr(string memory name) internal virtual returns (address addr) { + (addr,) = makeAddrAndKey(name); + } + + // Destroys an account immediately, sending the balance to beneficiary. + // Destroying means: balance will be zero, code will be empty, and nonce will be 0 + // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce + // only after tx ends, this will run immediately. + function destroyAccount(address who, address beneficiary) internal virtual { + uint256 currBalance = who.balance; + vm.etch(who, abi.encode()); + vm.deal(who, 0); + vm.resetNonce(who); + + uint256 beneficiaryBalance = beneficiary.balance; + vm.deal(beneficiary, currBalance + beneficiaryBalance); + } + + // creates a struct containing both a labeled address and the corresponding private key + function makeAccount(string memory name) internal virtual returns (Account memory account) { + (account.addr, account.key) = makeAddrAndKey(name); + } + + function deriveRememberKey(string memory mnemonic, uint32 index) + internal + virtual + returns (address who, uint256 privateKey) + { + privateKey = vm.deriveKey(mnemonic, index); + who = vm.rememberKey(privateKey); + } + + function _bytesToUint(bytes memory b) private pure returns (uint256) { + require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32."); + return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); + } + + function isFork() internal view virtual returns (bool status) { + try vm.activeFork() { + status = true; + } catch (bytes memory) {} + } + + modifier skipWhenForking() { + if (!isFork()) { + _; + } + } + + modifier skipWhenNotForking() { + if (isFork()) { + _; + } + } + + modifier noGasMetering() { + vm.pauseGasMetering(); + // To prevent turning gas monitoring back on with nested functions that use this modifier, + // we check if gasMetering started in the off position. If it did, we don't want to turn + // it back on until we exit the top level function that used the modifier + // + // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well. + // funcA will have `gasStartedOff` as false, funcB will have it as true, + // so we only turn metering back on at the end of the funcA + bool gasStartedOff = gasMeteringOff; + gasMeteringOff = true; + + _; + + // if gas metering was on when this modifier was called, turn it back on at the end + if (!gasStartedOff) { + gasMeteringOff = false; + vm.resumeGasMetering(); + } + } + + // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no + // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We + // can't simply access the chain ID in a normal view or pure function because the solc View Pure + // Checker changed `chainid` from pure to view in 0.8.0. + function _viewChainId() private view returns (uint256 chainId) { + // Assembly required since `block.chainid` was introduced in 0.8.0. + assembly { + chainId := chainid() + } + + address(this); // Silence warnings in older Solc versions. + } + + function _pureChainId() private pure returns (uint256 chainId) { + function() internal view returns (uint256) fnIn = _viewChainId; + function() internal pure returns (uint256) pureChainId; + assembly { + pureChainId := fnIn + } + chainId = pureChainId(); + } +} + +// Wrappers around cheatcodes to avoid footguns +abstract contract StdCheats is StdCheatsSafe { + using stdStorage for StdStorage; + + StdStorage private stdstore; + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + + // Skip forward or rewind time by the specified number of seconds + function skip(uint256 time) internal virtual { + vm.warp(block.timestamp + time); + } + + function rewind(uint256 time) internal virtual { + vm.warp(block.timestamp - time); + } + + // Setup a prank from an address that has some ether + function hoax(address msgSender) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.prank(msgSender); + } + + function hoax(address msgSender, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.prank(msgSender); + } + + function hoax(address msgSender, address origin) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.prank(msgSender, origin); + } + + function hoax(address msgSender, address origin, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.prank(msgSender, origin); + } + + // Start perpetual prank from an address that has some ether + function startHoax(address msgSender) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.startPrank(msgSender); + } + + function startHoax(address msgSender, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.startPrank(msgSender); + } + + // Start perpetual prank from an address that has some ether + // tx.origin is set to the origin parameter + function startHoax(address msgSender, address origin) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.startPrank(msgSender, origin); + } + + function startHoax(address msgSender, address origin, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.startPrank(msgSender, origin); + } + + function changePrank(address msgSender) internal virtual { + console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); + vm.stopPrank(); + vm.startPrank(msgSender); + } + + function changePrank(address msgSender, address txOrigin) internal virtual { + vm.stopPrank(); + vm.startPrank(msgSender, txOrigin); + } + + // The same as Vm's `deal` + // Use the alternative signature for ERC20 tokens + function deal(address to, uint256 give) internal virtual { + vm.deal(to, give); + } + + // Set the balance of an account for any ERC20 token + // Use the alternative signature to update `totalSupply` + function deal(address token, address to, uint256 give) internal virtual { + deal(token, to, give, false); + } + + // Set the balance of an account for any ERC1155 token + // Use the alternative signature to update `totalSupply` + function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { + dealERC1155(token, to, id, give, false); + } + + function deal(address token, address to, uint256 give, bool adjust) internal virtual { + // get current balance + (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); + uint256 prevBal = abi.decode(balData, (uint256)); + + // update balance + stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); + + // update total supply + if (adjust) { + (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd)); + uint256 totSup = abi.decode(totSupData, (uint256)); + if (give < prevBal) { + totSup -= (prevBal - give); + } else { + totSup += (give - prevBal); + } + stdstore.target(token).sig(0x18160ddd).checked_write(totSup); + } + } + + function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { + // get current balance + (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); + uint256 prevBal = abi.decode(balData, (uint256)); + + // update balance + stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); + + // update total supply + if (adjust) { + (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); + require( + totSupData.length != 0, + "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." + ); + uint256 totSup = abi.decode(totSupData, (uint256)); + if (give < prevBal) { + totSup -= (prevBal - give); + } else { + totSup += (give - prevBal); + } + stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); + } + } + + function dealERC721(address token, address to, uint256 id) internal virtual { + // check if token id is already minted and the actual owner. + (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); + require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); + + // get owner current balance + (, bytes memory fromBalData) = + token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address)))); + uint256 fromPrevBal = abi.decode(fromBalData, (uint256)); + + // get new user current balance + (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); + uint256 toPrevBal = abi.decode(toBalData, (uint256)); + + // update balances + stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); + stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); + + // update owner + stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); + } + + function deployCodeTo(string memory what, address where) internal virtual { + deployCodeTo(what, "", 0, where); + } + + function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { + deployCodeTo(what, args, 0, where); + } + + function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { + bytes memory creationCode = vm.getCode(what); + vm.etch(where, abi.encodePacked(creationCode, args)); + (bool success, bytes memory runtimeBytecode) = where.call{value: value}(""); + require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode."); + vm.etch(where, runtimeBytecode); + } + + // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. + function console2_log_StdCheats(string memory p0) private view { + (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); + status; + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdError.sol b/contracts/src/v0.8/vendor/forge-std/src/StdError.sol new file mode 100644 index 0000000000..a302191faa --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdError.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test +pragma solidity >=0.6.2 <0.9.0; + +library stdError { + bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); + bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); + bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); + bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); + bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); + bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); + bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); + bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); + bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol b/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol new file mode 100644 index 0000000000..7620cbf3d8 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +abstract contract StdInvariant { + struct FuzzSelector { + address addr; + bytes4[] selectors; + } + + struct FuzzArtifactSelector { + string artifact; + bytes4[] selectors; + } + + struct FuzzInterface { + address addr; + string[] artifacts; + } + + address[] private _excludedContracts; + address[] private _excludedSenders; + address[] private _targetedContracts; + address[] private _targetedSenders; + + string[] private _excludedArtifacts; + string[] private _targetedArtifacts; + + FuzzArtifactSelector[] private _targetedArtifactSelectors; + + FuzzSelector[] private _targetedSelectors; + + FuzzInterface[] private _targetedInterfaces; + + // Functions for users: + // These are intended to be called in tests. + + function excludeContract(address newExcludedContract_) internal { + _excludedContracts.push(newExcludedContract_); + } + + function excludeSender(address newExcludedSender_) internal { + _excludedSenders.push(newExcludedSender_); + } + + function excludeArtifact(string memory newExcludedArtifact_) internal { + _excludedArtifacts.push(newExcludedArtifact_); + } + + function targetArtifact(string memory newTargetedArtifact_) internal { + _targetedArtifacts.push(newTargetedArtifact_); + } + + function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal { + _targetedArtifactSelectors.push(newTargetedArtifactSelector_); + } + + function targetContract(address newTargetedContract_) internal { + _targetedContracts.push(newTargetedContract_); + } + + function targetSelector(FuzzSelector memory newTargetedSelector_) internal { + _targetedSelectors.push(newTargetedSelector_); + } + + function targetSender(address newTargetedSender_) internal { + _targetedSenders.push(newTargetedSender_); + } + + function targetInterface(FuzzInterface memory newTargetedInterface_) internal { + _targetedInterfaces.push(newTargetedInterface_); + } + + // Functions for forge: + // These are called by forge to run invariant tests and don't need to be called in tests. + + function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { + excludedArtifacts_ = _excludedArtifacts; + } + + function excludeContracts() public view returns (address[] memory excludedContracts_) { + excludedContracts_ = _excludedContracts; + } + + function excludeSenders() public view returns (address[] memory excludedSenders_) { + excludedSenders_ = _excludedSenders; + } + + function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { + targetedArtifacts_ = _targetedArtifacts; + } + + function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) { + targetedArtifactSelectors_ = _targetedArtifactSelectors; + } + + function targetContracts() public view returns (address[] memory targetedContracts_) { + targetedContracts_ = _targetedContracts; + } + + function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { + targetedSelectors_ = _targetedSelectors; + } + + function targetSenders() public view returns (address[] memory targetedSenders_) { + targetedSenders_ = _targetedSenders; + } + + function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) { + targetedInterfaces_ = _targetedInterfaces; + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol b/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol new file mode 100644 index 0000000000..6dbde83542 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.0 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {VmSafe} from "./Vm.sol"; + +// Helpers for parsing and writing JSON files +// To parse: +// ``` +// using stdJson for string; +// string memory json = vm.readFile(""); +// json.readUint(""); +// ``` +// To write: +// ``` +// using stdJson for string; +// string memory json = "json"; +// json.serialize("a", uint256(123)); +// string memory semiFinal = json.serialize("b", string("test")); +// string memory finalJson = json.serialize("c", semiFinal); +// finalJson.write(""); +// ``` + +library stdJson { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { + return vm.parseJson(json, key); + } + + function readUint(string memory json, string memory key) internal pure returns (uint256) { + return vm.parseJsonUint(json, key); + } + + function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { + return vm.parseJsonUintArray(json, key); + } + + function readInt(string memory json, string memory key) internal pure returns (int256) { + return vm.parseJsonInt(json, key); + } + + function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { + return vm.parseJsonIntArray(json, key); + } + + function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { + return vm.parseJsonBytes32(json, key); + } + + function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { + return vm.parseJsonBytes32Array(json, key); + } + + function readString(string memory json, string memory key) internal pure returns (string memory) { + return vm.parseJsonString(json, key); + } + + function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { + return vm.parseJsonStringArray(json, key); + } + + function readAddress(string memory json, string memory key) internal pure returns (address) { + return vm.parseJsonAddress(json, key); + } + + function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { + return vm.parseJsonAddressArray(json, key); + } + + function readBool(string memory json, string memory key) internal pure returns (bool) { + return vm.parseJsonBool(json, key); + } + + function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { + return vm.parseJsonBoolArray(json, key); + } + + function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { + return vm.parseJsonBytes(json, key); + } + + function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { + return vm.parseJsonBytesArray(json, key); + } + + function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { + return vm.serializeJson(jsonKey, rootObject); + } + + function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bool[] memory value) + internal + returns (string memory) + { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256[] memory value) + internal + returns (string memory) + { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256[] memory value) + internal + returns (string memory) + { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address[] memory value) + internal + returns (string memory) + { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string[] memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function write(string memory jsonKey, string memory path) internal { + vm.writeJson(jsonKey, path); + } + + function write(string memory jsonKey, string memory path, string memory valueKey) internal { + vm.writeJson(jsonKey, path, valueKey); + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol b/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol new file mode 100644 index 0000000000..459523bdac --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +library stdMath { + int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; + + function abs(int256 a) internal pure returns (uint256) { + // Required or it will fail when `a = type(int256).min` + if (a == INT256_MIN) { + return 57896044618658097711785492504343953926634992332820282019728792003956564819968; + } + + return uint256(a > 0 ? a : -a); + } + + function delta(uint256 a, uint256 b) internal pure returns (uint256) { + return a > b ? a - b : b - a; + } + + function delta(int256 a, int256 b) internal pure returns (uint256) { + // a and b are of the same sign + // this works thanks to two's complement, the left-most bit is the sign bit + if ((a ^ b) > -1) { + return delta(abs(a), abs(b)); + } + + // a and b are of opposite signs + return abs(a) + abs(b); + } + + function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 absDelta = delta(a, b); + + return absDelta * 1e18 / b; + } + + function percentDelta(int256 a, int256 b) internal pure returns (uint256) { + uint256 absDelta = delta(a, b); + uint256 absB = abs(b); + + return absDelta * 1e18 / absB; + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol b/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol new file mode 100644 index 0000000000..ffd668c555 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol @@ -0,0 +1,473 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {Vm} from "./Vm.sol"; + +struct FindData { + uint256 slot; + uint256 offsetLeft; + uint256 offsetRight; + bool found; +} + +struct StdStorage { + mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds; + bytes32[] _keys; + bytes4 _sig; + uint256 _depth; + address _target; + bytes32 _set; + bool _enable_packed_slots; + bytes _calldata; +} + +library stdStorageSafe { + event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot); + event WARNING_UninitedSlot(address who, uint256 slot); + + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + function sigs(string memory sigStr) internal pure returns (bytes4) { + return bytes4(keccak256(bytes(sigStr))); + } + + function getCallParams(StdStorage storage self) internal view returns (bytes memory) { + if (self._calldata.length == 0) { + return flatten(self._keys); + } else { + return self._calldata; + } + } + + // Calls target contract with configured parameters + function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { + bytes memory cald = abi.encodePacked(self._sig, getCallParams(self)); + (bool success, bytes memory rdat) = self._target.staticcall(cald); + bytes32 result = bytesToBytes32(rdat, 32 * self._depth); + + return (success, result); + } + + // Tries mutating slot value to determine if the targeted value is stored in it. + // If current value is 0, then we are setting slot value to type(uint256).max + // Otherwise, we set it to 0. That way, return value should always be affected. + function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { + bytes32 prevSlotValue = vm.load(self._target, slot); + (bool success, bytes32 prevReturnValue) = callTarget(self); + + bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0); + vm.store(self._target, slot, testVal); + + (, bytes32 newReturnValue) = callTarget(self); + + vm.store(self._target, slot, prevSlotValue); + + return (success && (prevReturnValue != newReturnValue)); + } + + // Tries setting one of the bits in slot to 1 until return value changes. + // Index of resulted bit is an offset packed slot has from left/right side + function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { + for (uint256 offset = 0; offset < 256; offset++) { + uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); + vm.store(self._target, slot, bytes32(valueToPut)); + + (bool success, bytes32 data) = callTarget(self); + + if (success && (uint256(data) > 0)) { + return (true, offset); + } + } + return (false, 0); + } + + function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { + bytes32 prevSlotValue = vm.load(self._target, slot); + + (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true); + (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false); + + // `findOffset` may mutate slot value, so we are setting it to initial value + vm.store(self._target, slot, prevSlotValue); + return (foundLeft && foundRight, offsetLeft, offsetRight); + } + + function find(StdStorage storage self) internal returns (FindData storage) { + return find(self, true); + } + + /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against + // slot complexity: + // if flat, will be bytes32(uint256(uint)); + // if map, will be keccak256(abi.encode(key, uint(slot))); + // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))); + // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth); + function find(StdStorage storage self, bool _clear) internal returns (FindData storage) { + address who = self._target; + bytes4 fsig = self._sig; + uint256 field_depth = self._depth; + bytes memory params = getCallParams(self); + + // calldata to test against + if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { + if (_clear) { + clear(self); + } + return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; + } + vm.record(); + (, bytes32 callResult) = callTarget(self); + (bytes32[] memory reads,) = vm.accesses(address(who)); + + if (reads.length == 0) { + revert("stdStorage find(StdStorage): No storage use detected for target."); + } else { + for (uint256 i = 0; i < reads.length; i++) { + bytes32 prev = vm.load(who, reads[i]); + if (prev == bytes32(0)) { + emit WARNING_UninitedSlot(who, uint256(reads[i])); + } + + if (!checkSlotMutatesCall(self, reads[i])) { + continue; + } + + (uint256 offsetLeft, uint256 offsetRight) = (0, 0); + + if (self._enable_packed_slots) { + bool found; + (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]); + if (!found) { + continue; + } + } + + // Check that value between found offsets is equal to the current call result + uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight; + + if (uint256(callResult) != curVal) { + continue; + } + + emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i])); + self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] = + FindData(uint256(reads[i]), offsetLeft, offsetRight, true); + break; + } + } + + require( + self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found, + "stdStorage find(StdStorage): Slot(s) not found." + ); + + if (_clear) { + clear(self); + } + return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; + } + + function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { + self._target = _target; + return self; + } + + function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { + self._sig = _sig; + return self; + } + + function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { + self._sig = sigs(_sig); + return self; + } + + function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { + self._calldata = _calldata; + return self; + } + + function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { + self._keys.push(bytes32(uint256(uint160(who)))); + return self; + } + + function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { + self._keys.push(bytes32(amt)); + return self; + } + + function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { + self._keys.push(key); + return self; + } + + function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { + self._enable_packed_slots = true; + return self; + } + + function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { + self._depth = _depth; + return self; + } + + function read(StdStorage storage self) private returns (bytes memory) { + FindData storage data = find(self, false); + uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); + uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; + clear(self); + return abi.encode(value); + } + + function read_bytes32(StdStorage storage self) internal returns (bytes32) { + return abi.decode(read(self), (bytes32)); + } + + function read_bool(StdStorage storage self) internal returns (bool) { + int256 v = read_int(self); + if (v == 0) return false; + if (v == 1) return true; + revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); + } + + function read_address(StdStorage storage self) internal returns (address) { + return abi.decode(read(self), (address)); + } + + function read_uint(StdStorage storage self) internal returns (uint256) { + return abi.decode(read(self), (uint256)); + } + + function read_int(StdStorage storage self) internal returns (int256) { + return abi.decode(read(self), (int256)); + } + + function parent(StdStorage storage self) internal returns (uint256, bytes32) { + address who = self._target; + uint256 field_depth = self._depth; + vm.startMappingRecording(); + uint256 child = find(self, true).slot - field_depth; + (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); + if (!found) { + revert( + "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." + ); + } + return (uint256(parent_slot), key); + } + + function root(StdStorage storage self) internal returns (uint256) { + address who = self._target; + uint256 field_depth = self._depth; + vm.startMappingRecording(); + uint256 child = find(self, true).slot - field_depth; + bool found; + bytes32 root_slot; + bytes32 parent_slot; + (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); + if (!found) { + revert( + "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." + ); + } + while (found) { + root_slot = parent_slot; + (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot)); + } + return uint256(root_slot); + } + + function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { + bytes32 out; + + uint256 max = b.length > 32 ? 32 : b.length; + for (uint256 i = 0; i < max; i++) { + out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); + } + return out; + } + + function flatten(bytes32[] memory b) private pure returns (bytes memory) { + bytes memory result = new bytes(b.length * 32); + for (uint256 i = 0; i < b.length; i++) { + bytes32 k = b[i]; + /// @solidity memory-safe-assembly + assembly { + mstore(add(result, add(32, mul(32, i))), k) + } + } + + return result; + } + + function clear(StdStorage storage self) internal { + delete self._target; + delete self._sig; + delete self._keys; + delete self._depth; + delete self._enable_packed_slots; + delete self._calldata; + } + + // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` + // (slotValue & mask) >> offsetRight will be the value of the given packed variable + function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { + // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; + // using assembly because (1 << 256) causes overflow + assembly { + mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1)) + } + } + + // Returns slot value with updated packed variable. + function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) + internal + pure + returns (bytes32 newValue) + { + return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight)); + } +} + +library stdStorage { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function sigs(string memory sigStr) internal pure returns (bytes4) { + return stdStorageSafe.sigs(sigStr); + } + + function find(StdStorage storage self) internal returns (uint256) { + return find(self, true); + } + + function find(StdStorage storage self, bool _clear) internal returns (uint256) { + return stdStorageSafe.find(self, _clear).slot; + } + + function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { + return stdStorageSafe.target(self, _target); + } + + function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { + return stdStorageSafe.sig(self, _sig); + } + + function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { + return stdStorageSafe.sig(self, _sig); + } + + function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { + return stdStorageSafe.with_key(self, who); + } + + function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { + return stdStorageSafe.with_key(self, amt); + } + + function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { + return stdStorageSafe.with_key(self, key); + } + + function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { + return stdStorageSafe.with_calldata(self, _calldata); + } + + function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { + return stdStorageSafe.enable_packed_slots(self); + } + + function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { + return stdStorageSafe.depth(self, _depth); + } + + function clear(StdStorage storage self) internal { + stdStorageSafe.clear(self); + } + + function checked_write(StdStorage storage self, address who) internal { + checked_write(self, bytes32(uint256(uint160(who)))); + } + + function checked_write(StdStorage storage self, uint256 amt) internal { + checked_write(self, bytes32(amt)); + } + + function checked_write_int(StdStorage storage self, int256 val) internal { + checked_write(self, bytes32(uint256(val))); + } + + function checked_write(StdStorage storage self, bool write) internal { + bytes32 t; + /// @solidity memory-safe-assembly + assembly { + t := write + } + checked_write(self, t); + } + + function checked_write(StdStorage storage self, bytes32 set) internal { + address who = self._target; + bytes4 fsig = self._sig; + uint256 field_depth = self._depth; + bytes memory params = stdStorageSafe.getCallParams(self); + + if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { + find(self, false); + } + FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; + if ((data.offsetLeft + data.offsetRight) > 0) { + uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight)); + require( + uint256(set) < maxVal, + string( + abi.encodePacked( + "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", + vm.toString(maxVal) + ) + ) + ); + } + bytes32 curVal = vm.load(who, bytes32(data.slot)); + bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight); + + vm.store(who, bytes32(data.slot), valToSet); + + (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self); + + if (!success || callResult != set) { + vm.store(who, bytes32(data.slot), curVal); + revert("stdStorage find(StdStorage): Failed to write value."); + } + clear(self); + } + + function read_bytes32(StdStorage storage self) internal returns (bytes32) { + return stdStorageSafe.read_bytes32(self); + } + + function read_bool(StdStorage storage self) internal returns (bool) { + return stdStorageSafe.read_bool(self); + } + + function read_address(StdStorage storage self) internal returns (address) { + return stdStorageSafe.read_address(self); + } + + function read_uint(StdStorage storage self) internal returns (uint256) { + return stdStorageSafe.read_uint(self); + } + + function read_int(StdStorage storage self) internal returns (int256) { + return stdStorageSafe.read_int(self); + } + + function parent(StdStorage storage self) internal returns (uint256, bytes32) { + return stdStorageSafe.parent(self); + } + + function root(StdStorage storage self) internal returns (uint256) { + return stdStorageSafe.root(self); + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol b/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol new file mode 100644 index 0000000000..d371e0c60a --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.22 <0.9.0; + +import {VmSafe} from "./Vm.sol"; + +library StdStyle { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + string constant RED = "\u001b[91m"; + string constant GREEN = "\u001b[92m"; + string constant YELLOW = "\u001b[93m"; + string constant BLUE = "\u001b[94m"; + string constant MAGENTA = "\u001b[95m"; + string constant CYAN = "\u001b[96m"; + string constant BOLD = "\u001b[1m"; + string constant DIM = "\u001b[2m"; + string constant ITALIC = "\u001b[3m"; + string constant UNDERLINE = "\u001b[4m"; + string constant INVERSE = "\u001b[7m"; + string constant RESET = "\u001b[0m"; + + function styleConcat(string memory style, string memory self) private pure returns (string memory) { + return string(abi.encodePacked(style, self, RESET)); + } + + function red(string memory self) internal pure returns (string memory) { + return styleConcat(RED, self); + } + + function red(uint256 self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function red(int256 self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function red(address self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function red(bool self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function redBytes(bytes memory self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function redBytes32(bytes32 self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function green(string memory self) internal pure returns (string memory) { + return styleConcat(GREEN, self); + } + + function green(uint256 self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function green(int256 self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function green(address self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function green(bool self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function greenBytes(bytes memory self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function greenBytes32(bytes32 self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function yellow(string memory self) internal pure returns (string memory) { + return styleConcat(YELLOW, self); + } + + function yellow(uint256 self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellow(int256 self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellow(address self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellow(bool self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellowBytes(bytes memory self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellowBytes32(bytes32 self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function blue(string memory self) internal pure returns (string memory) { + return styleConcat(BLUE, self); + } + + function blue(uint256 self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blue(int256 self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blue(address self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blue(bool self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blueBytes(bytes memory self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blueBytes32(bytes32 self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function magenta(string memory self) internal pure returns (string memory) { + return styleConcat(MAGENTA, self); + } + + function magenta(uint256 self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magenta(int256 self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magenta(address self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magenta(bool self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magentaBytes(bytes memory self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magentaBytes32(bytes32 self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function cyan(string memory self) internal pure returns (string memory) { + return styleConcat(CYAN, self); + } + + function cyan(uint256 self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyan(int256 self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyan(address self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyan(bool self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyanBytes(bytes memory self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyanBytes32(bytes32 self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function bold(string memory self) internal pure returns (string memory) { + return styleConcat(BOLD, self); + } + + function bold(uint256 self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function bold(int256 self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function bold(address self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function bold(bool self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function boldBytes(bytes memory self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function boldBytes32(bytes32 self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function dim(string memory self) internal pure returns (string memory) { + return styleConcat(DIM, self); + } + + function dim(uint256 self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dim(int256 self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dim(address self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dim(bool self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dimBytes(bytes memory self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dimBytes32(bytes32 self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function italic(string memory self) internal pure returns (string memory) { + return styleConcat(ITALIC, self); + } + + function italic(uint256 self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italic(int256 self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italic(address self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italic(bool self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italicBytes(bytes memory self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italicBytes32(bytes32 self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function underline(string memory self) internal pure returns (string memory) { + return styleConcat(UNDERLINE, self); + } + + function underline(uint256 self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underline(int256 self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underline(address self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underline(bool self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underlineBytes(bytes memory self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underlineBytes32(bytes32 self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function inverse(string memory self) internal pure returns (string memory) { + return styleConcat(INVERSE, self); + } + + function inverse(uint256 self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverse(int256 self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverse(address self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverse(bool self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverseBytes(bytes memory self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverseBytes32(bytes32 self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol b/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol new file mode 100644 index 0000000000..ef88db6d2f --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.0 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {VmSafe} from "./Vm.sol"; + +// Helpers for parsing and writing TOML files +// To parse: +// ``` +// using stdToml for string; +// string memory toml = vm.readFile(""); +// toml.readUint(""); +// ``` +// To write: +// ``` +// using stdToml for string; +// string memory json = "json"; +// json.serialize("a", uint256(123)); +// string memory semiFinal = json.serialize("b", string("test")); +// string memory finalJson = json.serialize("c", semiFinal); +// finalJson.write(""); +// ``` + +library stdToml { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { + return vm.parseToml(toml, key); + } + + function readUint(string memory toml, string memory key) internal pure returns (uint256) { + return vm.parseTomlUint(toml, key); + } + + function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) { + return vm.parseTomlUintArray(toml, key); + } + + function readInt(string memory toml, string memory key) internal pure returns (int256) { + return vm.parseTomlInt(toml, key); + } + + function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) { + return vm.parseTomlIntArray(toml, key); + } + + function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) { + return vm.parseTomlBytes32(toml, key); + } + + function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) { + return vm.parseTomlBytes32Array(toml, key); + } + + function readString(string memory toml, string memory key) internal pure returns (string memory) { + return vm.parseTomlString(toml, key); + } + + function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) { + return vm.parseTomlStringArray(toml, key); + } + + function readAddress(string memory toml, string memory key) internal pure returns (address) { + return vm.parseTomlAddress(toml, key); + } + + function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) { + return vm.parseTomlAddressArray(toml, key); + } + + function readBool(string memory toml, string memory key) internal pure returns (bool) { + return vm.parseTomlBool(toml, key); + } + + function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) { + return vm.parseTomlBoolArray(toml, key); + } + + function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) { + return vm.parseTomlBytes(toml, key); + } + + function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) { + return vm.parseTomlBytesArray(toml, key); + } + + function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { + return vm.serializeJson(jsonKey, rootObject); + } + + function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bool[] memory value) + internal + returns (string memory) + { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256[] memory value) + internal + returns (string memory) + { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256[] memory value) + internal + returns (string memory) + { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address[] memory value) + internal + returns (string memory) + { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string[] memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function write(string memory jsonKey, string memory path) internal { + vm.writeToml(jsonKey, path); + } + + function write(string memory jsonKey, string memory path, string memory valueKey) internal { + vm.writeToml(jsonKey, path, valueKey); + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol b/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol new file mode 100644 index 0000000000..5d120439fe --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {IMulticall3} from "./interfaces/IMulticall3.sol"; +import {MockERC20} from "./mocks/MockERC20.sol"; +import {MockERC721} from "./mocks/MockERC721.sol"; +import {VmSafe} from "./Vm.sol"; + +abstract contract StdUtils { + /*////////////////////////////////////////////////////////////////////////// + CONSTANTS + //////////////////////////////////////////////////////////////////////////*/ + + IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + uint256 private constant INT256_MIN_ABS = + 57896044618658097711785492504343953926634992332820282019728792003956564819968; + uint256 private constant SECP256K1_ORDER = + 115792089237316195423570985008687907852837564279074904382605163141518161494337; + uint256 private constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. + address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + + /*////////////////////////////////////////////////////////////////////////// + INTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////////////////*/ + + function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { + require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); + // If x is between min and max, return x directly. This is to ensure that dictionary values + // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 + if (x >= min && x <= max) return x; + + uint256 size = max - min + 1; + + // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. + // This helps ensure coverage of the min/max values. + if (x <= 3 && size > x) return min + x; + if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); + + // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. + if (x > max) { + uint256 diff = x - max; + uint256 rem = diff % size; + if (rem == 0) return max; + result = min + rem - 1; + } else if (x < min) { + uint256 diff = min - x; + uint256 rem = diff % size; + if (rem == 0) return min; + result = max - rem + 1; + } + } + + function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { + result = _bound(x, min, max); + console2_log_StdUtils("Bound result", result); + } + + function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { + require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); + + // Shifting all int256 values to uint256 to use _bound function. The range of two types are: + // int256 : -(2**255) ~ (2**255 - 1) + // uint256: 0 ~ (2**256 - 1) + // So, add 2**255, INT256_MIN_ABS to the integer values. + // + // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. + // So, use `~uint256(x) + 1` instead. + uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); + uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); + uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); + + uint256 y = _bound(_x, _min, _max); + + // To move it back to int256 value, subtract INT256_MIN_ABS at here. + result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); + } + + function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { + result = _bound(x, min, max); + console2_log_StdUtils("Bound result", vm.toString(result)); + } + + function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { + result = _bound(privateKey, 1, SECP256K1_ORDER - 1); + } + + function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { + require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); + return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); + } + + /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce + /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) + function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { + console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); + return vm.computeCreateAddress(deployer, nonce); + } + + function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) + internal + pure + virtual + returns (address) + { + console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); + return vm.computeCreate2Address(salt, initcodeHash, deployer); + } + + /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { + console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); + return vm.computeCreate2Address(salt, initCodeHash); + } + + /// @dev returns an initialized mock ERC20 contract + function deployMockERC20(string memory name, string memory symbol, uint8 decimals) + internal + returns (MockERC20 mock) + { + mock = new MockERC20(); + mock.initialize(name, symbol, decimals); + } + + /// @dev returns an initialized mock ERC721 contract + function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { + mock = new MockERC721(); + mock.initialize(name, symbol); + } + + /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments + /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode + function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { + return hashInitCode(creationCode, ""); + } + + /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 + /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode + /// @param args the ABI-encoded arguments to the constructor of C + function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(creationCode, args)); + } + + // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. + function getTokenBalances(address token, address[] memory addresses) + internal + virtual + returns (uint256[] memory balances) + { + uint256 tokenCodeSize; + assembly { + tokenCodeSize := extcodesize(token) + } + require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); + + // ABI encode the aggregate call to Multicall3. + uint256 length = addresses.length; + IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); + for (uint256 i = 0; i < length; ++i) { + // 0x70a08231 = bytes4("balanceOf(address)")) + calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); + } + + // Make the aggregate call. + (, bytes[] memory returnData) = multicall.aggregate(calls); + + // ABI decode the return data and return the balances. + balances = new uint256[](length); + for (uint256 i = 0; i < length; ++i) { + balances[i] = abi.decode(returnData[i], (uint256)); + } + } + + /*////////////////////////////////////////////////////////////////////////// + PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////////////////*/ + + function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { + return address(uint160(uint256(bytesValue))); + } + + // This section is used to prevent the compilation of console, which shortens the compilation time when console is + // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid + // any breaking changes to function signatures. + function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) + internal + pure + returns (function(bytes memory) internal pure fnOut) + { + assembly { + fnOut := fnIn + } + } + + function _sendLogPayload(bytes memory payload) internal pure { + _castLogPayloadViewToPure(_sendLogPayloadView)(payload); + } + + function _sendLogPayloadView(bytes memory payload) private view { + uint256 payloadLength = payload.length; + address consoleAddress = CONSOLE2_ADDRESS; + /// @solidity memory-safe-assembly + assembly { + let payloadStart := add(payload, 32) + let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) + } + } + + function console2_log_StdUtils(string memory p0) private pure { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function console2_log_StdUtils(string memory p0, uint256 p1) private pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); + } + + function console2_log_StdUtils(string memory p0, string memory p1) private pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/Test.sol b/contracts/src/v0.8/vendor/forge-std/src/Test.sol new file mode 100644 index 0000000000..5ff60ea3f6 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/Test.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +// 💬 ABOUT +// Forge Std's default Test. + +// 🧩 MODULES +import {console} from "./console.sol"; +import {console2} from "./console2.sol"; +import {safeconsole} from "./safeconsole.sol"; +import {StdAssertions} from "./StdAssertions.sol"; +import {StdChains} from "./StdChains.sol"; +import {StdCheats} from "./StdCheats.sol"; +import {stdError} from "./StdError.sol"; +import {StdInvariant} from "./StdInvariant.sol"; +import {stdJson} from "./StdJson.sol"; +import {stdMath} from "./StdMath.sol"; +import {StdStorage, stdStorage} from "./StdStorage.sol"; +import {StdStyle} from "./StdStyle.sol"; +import {stdToml} from "./StdToml.sol"; +import {StdUtils} from "./StdUtils.sol"; +import {Vm} from "./Vm.sol"; + +// 📦 BOILERPLATE +import {TestBase} from "./Base.sol"; + +// ⭐️ TEST +abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils { + // Note: IS_TEST() must return true. + bool public IS_TEST = true; +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/Vm.sol b/contracts/src/v0.8/vendor/forge-std/src/Vm.sol new file mode 100644 index 0000000000..6b1f2913cf --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/Vm.sol @@ -0,0 +1,1751 @@ +// Automatically @generated by scripts/vm.py. Do not modify manually. + +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may +/// result in Script simulations differing from on-chain execution. It is recommended to only use +/// these cheats in scripts. +interface VmSafe { + /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`. + enum CallerMode { + // No caller modification is currently active. + None, + // A one time broadcast triggered by a `vm.broadcast()` call is currently active. + Broadcast, + // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active. + RecurrentBroadcast, + // A one time prank triggered by a `vm.prank()` call is currently active. + Prank, + // A recurrent prank triggered by a `vm.startPrank()` call is currently active. + RecurrentPrank + } + + /// The kind of account access that occurred. + enum AccountAccessKind { + // The account was called. + Call, + // The account was called via delegatecall. + DelegateCall, + // The account was called via callcode. + CallCode, + // The account was called via staticcall. + StaticCall, + // The account was created. + Create, + // The account was selfdestructed. + SelfDestruct, + // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess). + Resume, + // The account's balance was read. + Balance, + // The account's codesize was read. + Extcodesize, + // The account's codehash was read. + Extcodehash, + // The account's code was copied. + Extcodecopy + } + + /// Forge execution contexts. + enum ForgeContext { + // Test group execution context (test, coverage or snapshot). + TestGroup, + // `forge test` execution context. + Test, + // `forge coverage` execution context. + Coverage, + // `forge snapshot` execution context. + Snapshot, + // Script group execution context (dry run, broadcast or resume). + ScriptGroup, + // `forge script` execution context. + ScriptDryRun, + // `forge script --broadcast` execution context. + ScriptBroadcast, + // `forge script --resume` execution context. + ScriptResume, + // Unknown `forge` execution context. + Unknown + } + + /// An Ethereum log. Returned by `getRecordedLogs`. + struct Log { + // The topics of the log, including the signature, if any. + bytes32[] topics; + // The raw data of the log. + bytes data; + // The address of the log's emitter. + address emitter; + } + + /// An RPC URL and its alias. Returned by `rpcUrlStructs`. + struct Rpc { + // The alias of the RPC URL. + string key; + // The RPC URL. + string url; + } + + /// An RPC log object. Returned by `eth_getLogs`. + struct EthGetLogs { + // The address of the log's emitter. + address emitter; + // The topics of the log, including the signature, if any. + bytes32[] topics; + // The raw data of the log. + bytes data; + // The block hash. + bytes32 blockHash; + // The block number. + uint64 blockNumber; + // The transaction hash. + bytes32 transactionHash; + // The transaction index in the block. + uint64 transactionIndex; + // The log index. + uint256 logIndex; + // Whether the log was removed. + bool removed; + } + + /// A single entry in a directory listing. Returned by `readDir`. + struct DirEntry { + // The error message, if any. + string errorMessage; + // The path of the entry. + string path; + // The depth of the entry. + uint64 depth; + // Whether the entry is a directory. + bool isDir; + // Whether the entry is a symlink. + bool isSymlink; + } + + /// Metadata information about a file. + /// This structure is returned from the `fsMetadata` function and represents known + /// metadata about a file such as its permissions, size, modification + /// times, etc. + struct FsMetadata { + // True if this metadata is for a directory. + bool isDir; + // True if this metadata is for a symlink. + bool isSymlink; + // The size of the file, in bytes, this metadata is for. + uint256 length; + // True if this metadata is for a readonly (unwritable) file. + bool readOnly; + // The last modification time listed in this metadata. + uint256 modified; + // The last access time of this metadata. + uint256 accessed; + // The creation time listed in this metadata. + uint256 created; + } + + /// A wallet with a public and private key. + struct Wallet { + // The wallet's address. + address addr; + // The wallet's public key `X`. + uint256 publicKeyX; + // The wallet's public key `Y`. + uint256 publicKeyY; + // The wallet's private key. + uint256 privateKey; + } + + /// The result of a `tryFfi` call. + struct FfiResult { + // The exit code of the call. + int32 exitCode; + // The optionally hex-decoded `stdout` data. + bytes stdout; + // The `stderr` data. + bytes stderr; + } + + /// Information on the chain and fork. + struct ChainInfo { + // The fork identifier. Set to zero if no fork is active. + uint256 forkId; + // The chain ID of the current fork. + uint256 chainId; + } + + /// The result of a `stopAndReturnStateDiff` call. + struct AccountAccess { + // The chain and fork the access occurred. + ChainInfo chainInfo; + // The kind of account access that determines what the account is. + // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee. + // If kind is Create, then the account is the newly created account. + // If kind is SelfDestruct, then the account is the selfdestruct recipient. + // If kind is a Resume, then account represents a account context that has resumed. + AccountAccessKind kind; + // The account that was accessed. + // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT. + address account; + // What accessed the account. + address accessor; + // If the account was initialized or empty prior to the access. + // An account is considered initialized if it has code, a + // non-zero nonce, or a non-zero balance. + bool initialized; + // The previous balance of the accessed account. + uint256 oldBalance; + // The potential new balance of the accessed account. + // That is, all balance changes are recorded here, even if reverts occurred. + uint256 newBalance; + // Code of the account deployed by CREATE. + bytes deployedCode; + // Value passed along with the account access + uint256 value; + // Input data provided to the CREATE or CALL + bytes data; + // If this access reverted in either the current or parent context. + bool reverted; + // An ordered list of storage accesses made during an account access operation. + StorageAccess[] storageAccesses; + // Call depth traversed during the recording of state differences + uint64 depth; + } + + /// The storage accessed during an `AccountAccess`. + struct StorageAccess { + // The account whose storage was accessed. + address account; + // The slot that was accessed. + bytes32 slot; + // If the access was a write. + bool isWrite; + // The previous value of the slot. + bytes32 previousValue; + // The new value of the slot. + bytes32 newValue; + // If the access was reverted. + bool reverted; + } + + /// Gas used. Returned by `lastCallGas`. + struct Gas { + // The gas limit of the call. + uint64 gasLimit; + // The total gas used. + uint64 gasTotalUsed; + // The amount of gas used for memory expansion. + uint64 gasMemoryUsed; + // The amount of gas refunded. + int64 gasRefunded; + // The amount of gas remaining. + uint64 gasRemaining; + } + + // ======== Environment ======== + + /// Gets the environment variable `name` and parses it as `address`. + /// Reverts if the variable was not found or could not be parsed. + function envAddress(string calldata name) external view returns (address value); + + /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); + + /// Gets the environment variable `name` and parses it as `bool`. + /// Reverts if the variable was not found or could not be parsed. + function envBool(string calldata name) external view returns (bool value); + + /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value); + + /// Gets the environment variable `name` and parses it as `bytes32`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes32(string calldata name) external view returns (bytes32 value); + + /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value); + + /// Gets the environment variable `name` and parses it as `bytes`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes(string calldata name) external view returns (bytes memory value); + + /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value); + + /// Gets the environment variable `name` and returns true if it exists, else returns false. + function envExists(string calldata name) external view returns (bool result); + + /// Gets the environment variable `name` and parses it as `int256`. + /// Reverts if the variable was not found or could not be parsed. + function envInt(string calldata name) external view returns (int256 value); + + /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value); + + /// Gets the environment variable `name` and parses it as `bool`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, bool defaultValue) external view returns (bool value); + + /// Gets the environment variable `name` and parses it as `uint256`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value); + + /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, address[] calldata defaultValue) + external + view + returns (address[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue) + external + view + returns (bytes32[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, string[] calldata defaultValue) + external + view + returns (string[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue) + external + view + returns (bytes[] memory value); + + /// Gets the environment variable `name` and parses it as `int256`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, int256 defaultValue) external view returns (int256 value); + + /// Gets the environment variable `name` and parses it as `address`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, address defaultValue) external view returns (address value); + + /// Gets the environment variable `name` and parses it as `bytes32`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value); + + /// Gets the environment variable `name` and parses it as `string`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value); + + /// Gets the environment variable `name` and parses it as `bytes`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value); + + /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue) + external + view + returns (bool[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue) + external + view + returns (uint256[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue) + external + view + returns (int256[] memory value); + + /// Gets the environment variable `name` and parses it as `string`. + /// Reverts if the variable was not found or could not be parsed. + function envString(string calldata name) external view returns (string memory value); + + /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envString(string calldata name, string calldata delim) external view returns (string[] memory value); + + /// Gets the environment variable `name` and parses it as `uint256`. + /// Reverts if the variable was not found or could not be parsed. + function envUint(string calldata name) external view returns (uint256 value); + + /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); + + /// Returns true if `forge` command was executed in given context. + function isContext(ForgeContext context) external view returns (bool result); + + /// Sets environment variables. + function setEnv(string calldata name, string calldata value) external; + + // ======== EVM ======== + + /// Gets all accessed reads and write slot from a `vm.record` session, for a given address. + function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots); + + /// Gets the address for a given private key. + function addr(uint256 privateKey) external pure returns (address keyAddr); + + /// Gets all the logs according to specified filter. + function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) + external + returns (EthGetLogs[] memory logs); + + /// Gets the current `block.blobbasefee`. + /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction, + /// and as a result will get optimized out by the compiler. + /// See https://github.com/foundry-rs/foundry/issues/6180 + function getBlobBaseFee() external view returns (uint256 blobBaseFee); + + /// Gets the current `block.number`. + /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction, + /// and as a result will get optimized out by the compiler. + /// See https://github.com/foundry-rs/foundry/issues/6180 + function getBlockNumber() external view returns (uint256 height); + + /// Gets the current `block.timestamp`. + /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction, + /// and as a result will get optimized out by the compiler. + /// See https://github.com/foundry-rs/foundry/issues/6180 + function getBlockTimestamp() external view returns (uint256 timestamp); + + /// Gets the map key and parent of a mapping at a given slot, for a given address. + function getMappingKeyAndParentOf(address target, bytes32 elementSlot) + external + returns (bool found, bytes32 key, bytes32 parent); + + /// Gets the number of elements in the mapping at the given slot, for a given address. + function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length); + + /// Gets the elements at index idx of the mapping at the given slot, for a given address. The + /// index must be less than the length of the mapping (i.e. the number of keys in the mapping). + function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value); + + /// Gets the nonce of an account. + function getNonce(address account) external view returns (uint64 nonce); + + /// Gets all the recorded logs. + function getRecordedLogs() external returns (Log[] memory logs); + + /// Gets the gas used in the last call. + function lastCallGas() external view returns (Gas memory gas); + + /// Loads a storage slot from an address. + function load(address target, bytes32 slot) external view returns (bytes32 data); + + /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused. + function pauseGasMetering() external; + + /// Records all storage reads and writes. + function record() external; + + /// Record all the transaction logs. + function recordLogs() external; + + /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. + function resumeGasMetering() external; + + /// Performs an Ethereum JSON-RPC request to the current fork URL. + function rpc(string calldata method, string calldata params) external returns (bytes memory data); + + /// Signs `digest` with `privateKey` using the secp256r1 curve. + function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); + + /// Signs `digest` with `privateKey` using the secp256k1 curve. + function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// If `--sender` is provided, the signer with provided address is used, otherwise, + /// if exactly one signer is provided to the script, that signer is used. + /// Raises error if signer passed through `--sender` does not match any unlocked signers or + /// if `--sender` is not provided and not exactly one signer is passed to the script. + function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Raises error if none of the signers passed into the script have provided address. + function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Starts recording all map SSTOREs for later retrieval. + function startMappingRecording() external; + + /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order, + /// along with the context of the calls + function startStateDiffRecording() external; + + /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. + function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); + + /// Stops recording all map SSTOREs for later retrieval and clears the recorded data. + function stopMappingRecording() external; + + // ======== Filesystem ======== + + /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. + /// `path` is relative to the project root. + function closeFile(string calldata path) external; + + /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`. + /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`. + /// Both `from` and `to` are relative to the project root. + function copyFile(string calldata from, string calldata to) external returns (uint64 copied); + + /// Creates a new, empty directory at the provided path. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - User lacks permissions to modify `path`. + /// - A parent of the given path doesn't exist and `recursive` is false. + /// - `path` already exists and `recursive` is false. + /// `path` is relative to the project root. + function createDir(string calldata path, bool recursive) external; + + /// Returns true if the given path points to an existing entity, else returns false. + function exists(string calldata path) external returns (bool result); + + /// Performs a foreign function call via the terminal. + function ffi(string[] calldata commandInput) external returns (bytes memory result); + + /// Given a path, query the file system to get information about a file, directory, etc. + function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); + + /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); + + /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); + + /// Returns true if the path exists on disk and is pointing at a directory, else returns false. + function isDir(string calldata path) external returns (bool result); + + /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. + function isFile(string calldata path) external returns (bool result); + + /// Get the path of the current project root. + function projectRoot() external view returns (string memory path); + + /// Prompts the user for a string value in the terminal. + function prompt(string calldata promptText) external returns (string memory input); + + /// Prompts the user for an address in the terminal. + function promptAddress(string calldata promptText) external returns (address); + + /// Prompts the user for a hidden string value in the terminal. + function promptSecret(string calldata promptText) external returns (string memory input); + + /// Prompts the user for uint256 in the terminal. + function promptUint(string calldata promptText) external returns (uint256); + + /// Reads the directory at the given path recursively, up to `maxDepth`. + /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned. + /// Follows symbolic links if `followLinks` is true. + function readDir(string calldata path) external view returns (DirEntry[] memory entries); + + /// See `readDir(string)`. + function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries); + + /// See `readDir(string)`. + function readDir(string calldata path, uint64 maxDepth, bool followLinks) + external + view + returns (DirEntry[] memory entries); + + /// Reads the entire content of file to string. `path` is relative to the project root. + function readFile(string calldata path) external view returns (string memory data); + + /// Reads the entire content of file as binary. `path` is relative to the project root. + function readFileBinary(string calldata path) external view returns (bytes memory data); + + /// Reads next line of file to string. + function readLine(string calldata path) external view returns (string memory line); + + /// Reads a symbolic link, returning the path that the link points to. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - `path` is not a symbolic link. + /// - `path` does not exist. + function readLink(string calldata linkPath) external view returns (string memory targetPath); + + /// Removes a directory at the provided path. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - `path` doesn't exist. + /// - `path` isn't a directory. + /// - User lacks permissions to modify `path`. + /// - The directory is not empty and `recursive` is false. + /// `path` is relative to the project root. + function removeDir(string calldata path, bool recursive) external; + + /// Removes a file from the filesystem. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - `path` points to a directory. + /// - The file doesn't exist. + /// - The user lacks permissions to remove the file. + /// `path` is relative to the project root. + function removeFile(string calldata path) external; + + /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr. + function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); + + /// Returns the time since unix epoch in milliseconds. + function unixTime() external returns (uint256 milliseconds); + + /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. + /// `path` is relative to the project root. + function writeFile(string calldata path, string calldata data) external; + + /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. + /// `path` is relative to the project root. + function writeFileBinary(string calldata path, bytes calldata data) external; + + /// Writes line to file, creating a file if it does not exist. + /// `path` is relative to the project root. + function writeLine(string calldata path, string calldata data) external; + + // ======== JSON ======== + + /// Checks if `key` exists in a JSON object + /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. + function keyExists(string calldata json, string calldata key) external view returns (bool); + + /// Checks if `key` exists in a JSON object. + function keyExistsJson(string calldata json, string calldata key) external view returns (bool); + + /// Parses a string of JSON data at `key` and coerces it to `address`. + function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); + + /// Parses a string of JSON data at `key` and coerces it to `address[]`. + function parseJsonAddressArray(string calldata json, string calldata key) + external + pure + returns (address[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `bool`. + function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); + + /// Parses a string of JSON data at `key` and coerces it to `bool[]`. + function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `bytes`. + function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory); + + /// Parses a string of JSON data at `key` and coerces it to `bytes32`. + function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); + + /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. + function parseJsonBytes32Array(string calldata json, string calldata key) + external + pure + returns (bytes32[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `bytes[]`. + function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `int256`. + function parseJsonInt(string calldata json, string calldata key) external pure returns (int256); + + /// Parses a string of JSON data at `key` and coerces it to `int256[]`. + function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory); + + /// Returns an array of all the keys in a JSON object. + function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); + + /// Parses a string of JSON data at `key` and coerces it to `string`. + function parseJsonString(string calldata json, string calldata key) external pure returns (string memory); + + /// Parses a string of JSON data at `key` and coerces it to `string[]`. + function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `uint256`. + function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); + + /// Parses a string of JSON data at `key` and coerces it to `uint256[]`. + function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory); + + /// ABI-encodes a JSON object. + function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData); + + /// ABI-encodes a JSON object at `key`. + function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData); + + /// See `serializeJson`. + function serializeAddress(string calldata objectKey, string calldata valueKey, address value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBool(string calldata objectKey, string calldata valueKey, bool value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeInt(string calldata objectKey, string calldata valueKey, int256 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values) + external + returns (string memory json); + + /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file. + /// Returns the stringified version of the specific JSON file up to that moment. + function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); + + /// See `serializeJson`. + function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values) + external + returns (string memory json); + + /// Write a serialized JSON object to a file. If the file exists, it will be overwritten. + function writeJson(string calldata json, string calldata path) external; + + /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = + /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. + function writeJson(string calldata json, string calldata path, string calldata valueKey) external; + + // ======== Scripting ======== + + /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. + /// Broadcasting address is determined by checking the following in order: + /// 1. If `--sender` argument was provided, that address is used. + /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. + /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. + function broadcast() external; + + /// Has the next call (at this call depth only) create a transaction with the address provided + /// as the sender that can later be signed and sent onchain. + function broadcast(address signer) external; + + /// Has the next call (at this call depth only) create a transaction with the private key + /// provided as the sender that can later be signed and sent onchain. + function broadcast(uint256 privateKey) external; + + /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. + /// Broadcasting address is determined by checking the following in order: + /// 1. If `--sender` argument was provided, that address is used. + /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. + /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. + function startBroadcast() external; + + /// Has all subsequent calls (at this call depth only) create transactions with the address + /// provided that can later be signed and sent onchain. + function startBroadcast(address signer) external; + + /// Has all subsequent calls (at this call depth only) create transactions with the private key + /// provided that can later be signed and sent onchain. + function startBroadcast(uint256 privateKey) external; + + /// Stops collecting onchain transactions. + function stopBroadcast() external; + + // ======== String ======== + + /// Returns the index of the first occurrence of a `key` in an `input` string. + /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found. + /// Returns 0 in case of an empty `key`. + function indexOf(string calldata input, string calldata key) external pure returns (uint256); + + /// Parses the given `string` into an `address`. + function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue); + + /// Parses the given `string` into a `bool`. + function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue); + + /// Parses the given `string` into `bytes`. + function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue); + + /// Parses the given `string` into a `bytes32`. + function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue); + + /// Parses the given `string` into a `int256`. + function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue); + + /// Parses the given `string` into a `uint256`. + function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue); + + /// Replaces occurrences of `from` in the given `string` with `to`. + function replace(string calldata input, string calldata from, string calldata to) + external + pure + returns (string memory output); + + /// Splits the given `string` into an array of strings divided by the `delimiter`. + function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); + + /// Converts the given `string` value to Lowercase. + function toLowercase(string calldata input) external pure returns (string memory output); + + /// Converts the given value to a `string`. + function toString(address value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(bytes calldata value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(bytes32 value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(bool value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(uint256 value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(int256 value) external pure returns (string memory stringifiedValue); + + /// Converts the given `string` value to Uppercase. + function toUppercase(string calldata input) external pure returns (string memory output); + + /// Trims leading and trailing whitespace from the given `string` value. + function trim(string calldata input) external pure returns (string memory output); + + // ======== Testing ======== + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqAbsDecimal( + uint256 left, + uint256 right, + uint256 maxDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqAbsDecimal( + int256 left, + int256 right, + uint256 maxDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + /// Includes error message into revert string on failure. + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + /// Includes error message into revert string on failure. + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. + function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) + external + pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. + function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) + external + pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Includes error message into revert string on failure. + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) + external + pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Includes error message into revert string on failure. + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) + external + pure; + + /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. + function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `bool` values are equal. + function assertEq(bool left, bool right) external pure; + + /// Asserts that two `bool` values are equal and includes error message into revert string on failure. + function assertEq(bool left, bool right, string calldata error) external pure; + + /// Asserts that two `string` values are equal. + function assertEq(string calldata left, string calldata right) external pure; + + /// Asserts that two `string` values are equal and includes error message into revert string on failure. + function assertEq(string calldata left, string calldata right, string calldata error) external pure; + + /// Asserts that two `bytes` values are equal. + function assertEq(bytes calldata left, bytes calldata right) external pure; + + /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. + function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bool` values are equal. + function assertEq(bool[] calldata left, bool[] calldata right) external pure; + + /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. + function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `uint256 values are equal. + function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; + + /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. + function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `int256` values are equal. + function assertEq(int256[] calldata left, int256[] calldata right) external pure; + + /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. + function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are equal. + function assertEq(uint256 left, uint256 right) external pure; + + /// Asserts that two arrays of `address` values are equal. + function assertEq(address[] calldata left, address[] calldata right) external pure; + + /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. + function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes32` values are equal. + function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; + + /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. + function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `string` values are equal. + function assertEq(string[] calldata left, string[] calldata right) external pure; + + /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. + function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes` values are equal. + function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; + + /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. + function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. + function assertEq(uint256 left, uint256 right, string calldata error) external pure; + + /// Asserts that two `int256` values are equal. + function assertEq(int256 left, int256 right) external pure; + + /// Asserts that two `int256` values are equal and includes error message into revert string on failure. + function assertEq(int256 left, int256 right, string calldata error) external pure; + + /// Asserts that two `address` values are equal. + function assertEq(address left, address right) external pure; + + /// Asserts that two `address` values are equal and includes error message into revert string on failure. + function assertEq(address left, address right, string calldata error) external pure; + + /// Asserts that two `bytes32` values are equal. + function assertEq(bytes32 left, bytes32 right) external pure; + + /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. + function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; + + /// Asserts that the given condition is false. + function assertFalse(bool condition) external pure; + + /// Asserts that the given condition is false and includes error message into revert string on failure. + function assertFalse(bool condition, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. + function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + function assertGe(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + /// Includes error message into revert string on failure. + function assertGe(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + function assertGe(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + /// Includes error message into revert string on failure. + function assertGe(int256 left, int256 right, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. + function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + function assertGt(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + /// Includes error message into revert string on failure. + function assertGt(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + function assertGt(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + /// Includes error message into revert string on failure. + function assertGt(int256 left, int256 right, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. + function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + function assertLe(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + /// Includes error message into revert string on failure. + function assertLe(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + function assertLe(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + /// Includes error message into revert string on failure. + function assertLe(int256 left, int256 right, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. + function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + function assertLt(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + /// Includes error message into revert string on failure. + function assertLt(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + function assertLt(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + /// Includes error message into revert string on failure. + function assertLt(int256 left, int256 right, string calldata error) external pure; + + /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `bool` values are not equal. + function assertNotEq(bool left, bool right) external pure; + + /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. + function assertNotEq(bool left, bool right, string calldata error) external pure; + + /// Asserts that two `string` values are not equal. + function assertNotEq(string calldata left, string calldata right) external pure; + + /// Asserts that two `string` values are not equal and includes error message into revert string on failure. + function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; + + /// Asserts that two `bytes` values are not equal. + function assertNotEq(bytes calldata left, bytes calldata right) external pure; + + /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bool` values are not equal. + function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; + + /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. + function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `uint256` values are not equal. + function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; + + /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. + function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `int256` values are not equal. + function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; + + /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. + function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are not equal. + function assertNotEq(uint256 left, uint256 right) external pure; + + /// Asserts that two arrays of `address` values are not equal. + function assertNotEq(address[] calldata left, address[] calldata right) external pure; + + /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. + function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes32` values are not equal. + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; + + /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `string` values are not equal. + function assertNotEq(string[] calldata left, string[] calldata right) external pure; + + /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. + function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes` values are not equal. + function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; + + /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. + function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; + + /// Asserts that two `int256` values are not equal. + function assertNotEq(int256 left, int256 right) external pure; + + /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. + function assertNotEq(int256 left, int256 right, string calldata error) external pure; + + /// Asserts that two `address` values are not equal. + function assertNotEq(address left, address right) external pure; + + /// Asserts that two `address` values are not equal and includes error message into revert string on failure. + function assertNotEq(address left, address right, string calldata error) external pure; + + /// Asserts that two `bytes32` values are not equal. + function assertNotEq(bytes32 left, bytes32 right) external pure; + + /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; + + /// Asserts that the given condition is true. + function assertTrue(bool condition) external pure; + + /// Asserts that the given condition is true and includes error message into revert string on failure. + function assertTrue(bool condition, string calldata error) external pure; + + /// If the condition is false, discard this run's fuzz inputs and generate new ones. + function assume(bool condition) external pure; + + /// Writes a breakpoint to jump to in the debugger. + function breakpoint(string calldata char) external; + + /// Writes a conditional breakpoint to jump to in the debugger. + function breakpoint(string calldata char, bool value) external; + + /// Returns the RPC url for the given alias. + function rpcUrl(string calldata rpcAlias) external view returns (string memory json); + + /// Returns all rpc urls and their aliases as structs. + function rpcUrlStructs() external view returns (Rpc[] memory urls); + + /// Returns all rpc urls and their aliases `[alias, url][]`. + function rpcUrls() external view returns (string[2][] memory urls); + + /// Suspends execution of the main thread for `duration` milliseconds. + function sleep(uint256 duration) external; + + // ======== Toml ======== + + /// Checks if `key` exists in a TOML table. + function keyExistsToml(string calldata toml, string calldata key) external view returns (bool); + + /// Parses a string of TOML data at `key` and coerces it to `address`. + function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); + + /// Parses a string of TOML data at `key` and coerces it to `address[]`. + function parseTomlAddressArray(string calldata toml, string calldata key) + external + pure + returns (address[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `bool`. + function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); + + /// Parses a string of TOML data at `key` and coerces it to `bool[]`. + function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `bytes`. + function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory); + + /// Parses a string of TOML data at `key` and coerces it to `bytes32`. + function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); + + /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. + function parseTomlBytes32Array(string calldata toml, string calldata key) + external + pure + returns (bytes32[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `bytes[]`. + function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `int256`. + function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256); + + /// Parses a string of TOML data at `key` and coerces it to `int256[]`. + function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory); + + /// Returns an array of all the keys in a TOML table. + function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys); + + /// Parses a string of TOML data at `key` and coerces it to `string`. + function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory); + + /// Parses a string of TOML data at `key` and coerces it to `string[]`. + function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `uint256`. + function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); + + /// Parses a string of TOML data at `key` and coerces it to `uint256[]`. + function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory); + + /// ABI-encodes a TOML table. + function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData); + + /// ABI-encodes a TOML table at `key`. + function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData); + + /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file. + function writeToml(string calldata json, string calldata path) external; + + /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = + /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing. + function writeToml(string calldata json, string calldata path, string calldata valueKey) external; + + // ======== Utilities ======== + + /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) + external + pure + returns (address); + + /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); + + /// Compute the address a contract will be deployed at for a given deployer address and nonce. + function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); + + /// Derives a private key from the name, labels the account with that name, and returns the wallet. + function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); + + /// Generates a wallet from the private key and returns the wallet. + function createWallet(uint256 privateKey) external returns (Wallet memory wallet); + + /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. + function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) + /// at the derivation path `m/44'/60'/0'/0/{index}`. + function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) + /// at `{derivationPath}{index}`. + function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) + external + pure + returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language + /// at the derivation path `m/44'/60'/0'/0/{index}`. + function deriveKey(string calldata mnemonic, uint32 index, string calldata language) + external + pure + returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language + /// at `{derivationPath}{index}`. + function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) + external + pure + returns (uint256 privateKey); + + /// Returns ENS namehash for provided string. + function ensNamehash(string calldata name) external pure returns (bytes32); + + /// Gets the label for the specified address. + function getLabel(address account) external view returns (string memory currentLabel); + + /// Get a `Wallet`'s nonce. + function getNonce(Wallet calldata wallet) external returns (uint64 nonce); + + /// Labels an address in call traces. + function label(address account, string calldata newLabel) external; + + /// Adds a private key to the local forge wallet and returns the address. + function rememberKey(uint256 privateKey) external returns (address keyAddr); + + /// Signs data with a `Wallet`. + function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + + /// Encodes a `bytes` value to a base64url string. + function toBase64URL(bytes calldata data) external pure returns (string memory); + + /// Encodes a `string` value to a base64url string. + function toBase64URL(string calldata data) external pure returns (string memory); + + /// Encodes a `bytes` value to a base64 string. + function toBase64(bytes calldata data) external pure returns (string memory); + + /// Encodes a `string` value to a base64 string. + function toBase64(string calldata data) external pure returns (string memory); +} + +/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used +/// in tests, but it is not recommended to use these cheats in scripts. +interface Vm is VmSafe { + // ======== EVM ======== + + /// Returns the identifier of the currently active fork. Reverts if no fork is currently active. + function activeFork() external view returns (uint256 forkId); + + /// In forking mode, explicitly grant the given address cheatcode access. + function allowCheatcodes(address account) external; + + /// Sets `block.blobbasefee` + function blobBaseFee(uint256 newBlobBaseFee) external; + + /// Sets the blobhashes in the transaction. + /// Not available on EVM versions before Cancun. + /// If used on unsupported EVM versions it will revert. + function blobhashes(bytes32[] calldata hashes) external; + + /// Sets `block.chainid`. + function chainId(uint256 newChainId) external; + + /// Clears all mocked calls. + function clearMockedCalls() external; + + /// Sets `block.coinbase`. + function coinbase(address newCoinbase) external; + + /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork. + function createFork(string calldata urlOrAlias) external returns (uint256 forkId); + + /// Creates a new fork with the given endpoint and block and returns the identifier of the fork. + function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); + + /// Creates a new fork with the given endpoint and at the block the given transaction was mined in, + /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork. + function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); + + /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork. + function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId); + + /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork. + function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); + + /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, + /// replays all transaction mined in the block before the transaction, returns the identifier of the fork. + function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); + + /// Sets an address' balance. + function deal(address account, uint256 newBalance) external; + + /// Removes the snapshot with the given ID created by `snapshot`. + /// Takes the snapshot ID to delete. + /// Returns `true` if the snapshot was successfully deleted. + /// Returns `false` if the snapshot does not exist. + function deleteSnapshot(uint256 snapshotId) external returns (bool success); + + /// Removes _all_ snapshots previously created by `snapshot`. + function deleteSnapshots() external; + + /// Sets `block.difficulty`. + /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. + /// Reverts if used on unsupported EVM versions. + function difficulty(uint256 newDifficulty) external; + + /// Dump a genesis JSON file's `allocs` to disk. + function dumpState(string calldata pathToStateJson) external; + + /// Sets an address' code. + function etch(address target, bytes calldata newRuntimeBytecode) external; + + /// Sets `block.basefee`. + function fee(uint256 newBasefee) external; + + /// Gets the blockhashes from the current transaction. + /// Not available on EVM versions before Cancun. + /// If used on unsupported EVM versions it will revert. + function getBlobhashes() external view returns (bytes32[] memory hashes); + + /// Returns true if the account is marked as persistent. + function isPersistent(address account) external view returns (bool persistent); + + /// Load a genesis JSON file's `allocs` into the in-memory revm state. + function loadAllocs(string calldata pathToAllocsJson) external; + + /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup + /// Meaning, changes made to the state of this account will be kept when switching forks. + function makePersistent(address account) external; + + /// See `makePersistent(address)`. + function makePersistent(address account0, address account1) external; + + /// See `makePersistent(address)`. + function makePersistent(address account0, address account1, address account2) external; + + /// See `makePersistent(address)`. + function makePersistent(address[] calldata accounts) external; + + /// Reverts a call to an address with specified revert data. + function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; + + /// Reverts a call to an address with a specific `msg.value`, with specified revert data. + function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) + external; + + /// Mocks a call to an address, returning specified data. + /// Calldata can either be strict or a partial match, e.g. if you only + /// pass a Solidity selector to the expected calldata, then the entire Solidity + /// function will be mocked. + function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; + + /// Mocks a call to an address with a specific `msg.value`, returning specified data. + /// Calldata match takes precedence over `msg.value` in case of ambiguity. + function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + + /// Sets the *next* call's `msg.sender` to be the input address. + function prank(address msgSender) external; + + /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. + function prank(address msgSender, address txOrigin) external; + + /// Sets `block.prevrandao`. + /// Not available on EVM versions before Paris. Use `difficulty` instead. + /// If used on unsupported EVM versions it will revert. + function prevrandao(bytes32 newPrevrandao) external; + + /// Sets `block.prevrandao`. + /// Not available on EVM versions before Paris. Use `difficulty` instead. + /// If used on unsupported EVM versions it will revert. + function prevrandao(uint256 newPrevrandao) external; + + /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification. + function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin); + + /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts. + function resetNonce(address account) external; + + /// Revert the state of the EVM to a previous snapshot + /// Takes the snapshot ID to revert to. + /// Returns `true` if the snapshot was successfully reverted. + /// Returns `false` if the snapshot does not exist. + /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. + function revertTo(uint256 snapshotId) external returns (bool success); + + /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots + /// Takes the snapshot ID to revert to. + /// Returns `true` if the snapshot was successfully reverted and deleted. + /// Returns `false` if the snapshot does not exist. + function revertToAndDelete(uint256 snapshotId) external returns (bool success); + + /// Revokes persistent status from the address, previously added via `makePersistent`. + function revokePersistent(address account) external; + + /// See `revokePersistent(address)`. + function revokePersistent(address[] calldata accounts) external; + + /// Sets `block.height`. + function roll(uint256 newHeight) external; + + /// Updates the currently active fork to given block number + /// This is similar to `roll` but for the currently active fork. + function rollFork(uint256 blockNumber) external; + + /// Updates the currently active fork to given transaction. This will `rollFork` with the number + /// of the block the transaction was mined in and replays all transaction mined before it in the block. + function rollFork(bytes32 txHash) external; + + /// Updates the given fork to given block number. + function rollFork(uint256 forkId, uint256 blockNumber) external; + + /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block. + function rollFork(uint256 forkId, bytes32 txHash) external; + + /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. + function selectFork(uint256 forkId) external; + + /// Sets the nonce of an account. Must be higher than the current nonce of the account. + function setNonce(address account, uint64 newNonce) external; + + /// Sets the nonce of an account to an arbitrary value. + function setNonceUnsafe(address account, uint64 newNonce) external; + + /// Snapshot the current state of the evm. + /// Returns the ID of the snapshot that was created. + /// To revert a snapshot use `revertTo`. + function snapshot() external returns (uint256 snapshotId); + + /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. + function startPrank(address msgSender) external; + + /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. + function startPrank(address msgSender, address txOrigin) external; + + /// Resets subsequent calls' `msg.sender` to be `address(this)`. + function stopPrank() external; + + /// Stores a value to an address' storage slot. + function store(address target, bytes32 slot, bytes32 value) external; + + /// Fetches the given transaction from the active fork and executes it on the current state. + function transact(bytes32 txHash) external; + + /// Fetches the given transaction from the given fork and executes it on the current state. + function transact(uint256 forkId, bytes32 txHash) external; + + /// Sets `tx.gasprice`. + function txGasPrice(uint256 newGasPrice) external; + + /// Sets `block.timestamp`. + function warp(uint256 newTimestamp) external; + + // ======== Testing ======== + + /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. + function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; + + /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. + function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) + external; + + /// Expects a call to an address with the specified calldata. + /// Calldata can either be a strict or a partial match. + function expectCall(address callee, bytes calldata data) external; + + /// Expects given number of calls to an address with the specified calldata. + function expectCall(address callee, bytes calldata data, uint64 count) external; + + /// Expects a call to an address with the specified `msg.value` and calldata. + function expectCall(address callee, uint256 msgValue, bytes calldata data) external; + + /// Expects given number of calls to an address with the specified `msg.value` and calldata. + function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external; + + /// Expect a call to an address with the specified `msg.value`, gas, and calldata. + function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external; + + /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. + function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; + + /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). + /// Call this function, then emit an event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). + function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) + external; + + /// Prepare an expected log with all topic and data checks enabled. + /// Call this function, then emit an event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data. + function expectEmit() external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmit(address emitter) external; + + /// Expects an error on next call with any revert data. + function expectRevert() external; + + /// Expects an error on next call that starts with the revert data. + function expectRevert(bytes4 revertData) external; + + /// Expects an error on next call that exactly matches the revert data. + function expectRevert(bytes calldata revertData) external; + + /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other + /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. + function expectSafeMemory(uint64 min, uint64 max) external; + + /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext. + /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges + /// to the set. + function expectSafeMemoryCall(uint64 min, uint64 max) external; + + /// Marks a test as skipped. Must be called at the top of the test. + function skip(bool skipTest) external; + + /// Stops all safe memory expectation in the current subcontext. + function stopExpectSafeMemory() external; +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/console.sol b/contracts/src/v0.8/vendor/forge-std/src/console.sol new file mode 100644 index 0000000000..ad57e53687 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/console.sol @@ -0,0 +1,1533 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.22 <0.9.0; + +library console { + address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); + + function _sendLogPayload(bytes memory payload) private view { + uint256 payloadLength = payload.length; + address consoleAddress = CONSOLE_ADDRESS; + /// @solidity memory-safe-assembly + assembly { + let payloadStart := add(payload, 32) + let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) + } + } + + function log() internal view { + _sendLogPayload(abi.encodeWithSignature("log()")); + } + + function logInt(int p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); + } + + function logUint(uint p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); + } + + function logString(string memory p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function logBool(bool p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); + } + + function logAddress(address p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); + } + + function logBytes(bytes memory p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); + } + + function logBytes1(bytes1 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); + } + + function logBytes2(bytes2 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); + } + + function logBytes3(bytes3 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); + } + + function logBytes4(bytes4 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); + } + + function logBytes5(bytes5 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); + } + + function logBytes6(bytes6 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); + } + + function logBytes7(bytes7 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); + } + + function logBytes8(bytes8 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); + } + + function logBytes9(bytes9 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); + } + + function logBytes10(bytes10 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); + } + + function logBytes11(bytes11 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); + } + + function logBytes12(bytes12 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); + } + + function logBytes13(bytes13 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); + } + + function logBytes14(bytes14 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); + } + + function logBytes15(bytes15 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); + } + + function logBytes16(bytes16 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); + } + + function logBytes17(bytes17 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); + } + + function logBytes18(bytes18 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); + } + + function logBytes19(bytes19 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); + } + + function logBytes20(bytes20 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); + } + + function logBytes21(bytes21 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); + } + + function logBytes22(bytes22 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); + } + + function logBytes23(bytes23 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); + } + + function logBytes24(bytes24 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); + } + + function logBytes25(bytes25 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); + } + + function logBytes26(bytes26 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); + } + + function logBytes27(bytes27 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); + } + + function logBytes28(bytes28 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); + } + + function logBytes29(bytes29 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); + } + + function logBytes30(bytes30 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); + } + + function logBytes31(bytes31 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); + } + + function logBytes32(bytes32 p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); + } + + function log(uint p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); + } + + function log(string memory p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function log(bool p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); + } + + function log(address p0) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); + } + + function log(uint p0, uint p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); + } + + function log(uint p0, string memory p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); + } + + function log(uint p0, bool p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); + } + + function log(uint p0, address p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); + } + + function log(string memory p0, uint p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); + } + + function log(string memory p0, string memory p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); + } + + function log(string memory p0, bool p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); + } + + function log(string memory p0, address p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); + } + + function log(bool p0, uint p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); + } + + function log(bool p0, string memory p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); + } + + function log(bool p0, bool p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); + } + + function log(bool p0, address p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); + } + + function log(address p0, uint p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); + } + + function log(address p0, string memory p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); + } + + function log(address p0, bool p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); + } + + function log(address p0, address p1) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); + } + + function log(uint p0, uint p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); + } + + function log(uint p0, uint p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); + } + + function log(uint p0, uint p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); + } + + function log(uint p0, uint p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); + } + + function log(uint p0, string memory p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); + } + + function log(uint p0, string memory p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); + } + + function log(uint p0, string memory p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); + } + + function log(uint p0, string memory p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); + } + + function log(uint p0, bool p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); + } + + function log(uint p0, bool p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); + } + + function log(uint p0, bool p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); + } + + function log(uint p0, bool p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); + } + + function log(uint p0, address p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); + } + + function log(uint p0, address p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); + } + + function log(uint p0, address p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); + } + + function log(uint p0, address p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); + } + + function log(string memory p0, uint p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); + } + + function log(string memory p0, uint p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); + } + + function log(string memory p0, uint p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); + } + + function log(string memory p0, uint p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); + } + + function log(string memory p0, address p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); + } + + function log(string memory p0, address p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); + } + + function log(string memory p0, address p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); + } + + function log(string memory p0, address p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); + } + + function log(bool p0, uint p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); + } + + function log(bool p0, uint p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); + } + + function log(bool p0, uint p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); + } + + function log(bool p0, uint p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); + } + + function log(bool p0, bool p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); + } + + function log(bool p0, bool p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); + } + + function log(bool p0, bool p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); + } + + function log(bool p0, bool p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); + } + + function log(bool p0, address p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); + } + + function log(bool p0, address p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); + } + + function log(bool p0, address p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); + } + + function log(bool p0, address p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); + } + + function log(address p0, uint p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); + } + + function log(address p0, uint p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); + } + + function log(address p0, uint p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); + } + + function log(address p0, uint p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); + } + + function log(address p0, string memory p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); + } + + function log(address p0, string memory p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); + } + + function log(address p0, string memory p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); + } + + function log(address p0, string memory p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); + } + + function log(address p0, bool p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); + } + + function log(address p0, bool p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); + } + + function log(address p0, bool p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); + } + + function log(address p0, bool p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); + } + + function log(address p0, address p1, uint p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); + } + + function log(address p0, address p1, string memory p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); + } + + function log(address p0, address p1, bool p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); + } + + function log(address p0, address p1, address p2) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); + } + + function log(uint p0, uint p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, uint p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, string memory p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, bool p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); + } + + function log(uint p0, address p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, uint p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, string memory p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, bool p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, address p3) internal view { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); + } + +} \ No newline at end of file diff --git a/contracts/src/v0.8/vendor/forge-std/src/console2.sol b/contracts/src/v0.8/vendor/forge-std/src/console2.sol new file mode 100644 index 0000000000..c1e2cd7546 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/console2.sol @@ -0,0 +1,1558 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.22 <0.9.0; + +/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should +/// use `int256` and `uint256`. This modified version fixes that. This version is recommended +/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in +/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`. +/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178 +library console2 { + address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); + + function _castLogPayloadViewToPure( + function(bytes memory) internal view fnIn + ) internal pure returns (function(bytes memory) internal pure fnOut) { + assembly { + fnOut := fnIn + } + } + + function _sendLogPayload(bytes memory payload) internal pure { + _castLogPayloadViewToPure(_sendLogPayloadView)(payload); + } + + function _sendLogPayloadView(bytes memory payload) private view { + uint256 payloadLength = payload.length; + address consoleAddress = CONSOLE_ADDRESS; + /// @solidity memory-safe-assembly + assembly { + let payloadStart := add(payload, 32) + let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) + } + } + + function log() internal pure { + _sendLogPayload(abi.encodeWithSignature("log()")); + } + + function logInt(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); + } + + function logUint(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); + } + + function logString(string memory p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function logBool(bool p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); + } + + function logAddress(address p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); + } + + function logBytes(bytes memory p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); + } + + function logBytes1(bytes1 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); + } + + function logBytes2(bytes2 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); + } + + function logBytes3(bytes3 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); + } + + function logBytes4(bytes4 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); + } + + function logBytes5(bytes5 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); + } + + function logBytes6(bytes6 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); + } + + function logBytes7(bytes7 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); + } + + function logBytes8(bytes8 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); + } + + function logBytes9(bytes9 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); + } + + function logBytes10(bytes10 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); + } + + function logBytes11(bytes11 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); + } + + function logBytes12(bytes12 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); + } + + function logBytes13(bytes13 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); + } + + function logBytes14(bytes14 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); + } + + function logBytes15(bytes15 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); + } + + function logBytes16(bytes16 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); + } + + function logBytes17(bytes17 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); + } + + function logBytes18(bytes18 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); + } + + function logBytes19(bytes19 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); + } + + function logBytes20(bytes20 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); + } + + function logBytes21(bytes21 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); + } + + function logBytes22(bytes22 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); + } + + function logBytes23(bytes23 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); + } + + function logBytes24(bytes24 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); + } + + function logBytes25(bytes25 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); + } + + function logBytes26(bytes26 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); + } + + function logBytes27(bytes27 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); + } + + function logBytes28(bytes28 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); + } + + function logBytes29(bytes29 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); + } + + function logBytes30(bytes30 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); + } + + function logBytes31(bytes31 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); + } + + function logBytes32(bytes32 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); + } + + function log(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); + } + + function log(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); + } + + function log(string memory p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function log(bool p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); + } + + function log(address p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); + } + + function log(uint256 p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); + } + + function log(uint256 p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); + } + + function log(uint256 p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); + } + + function log(uint256 p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); + } + + function log(string memory p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); + } + + function log(string memory p0, int256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); + } + + function log(string memory p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); + } + + function log(string memory p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); + } + + function log(string memory p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); + } + + function log(bool p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); + } + + function log(bool p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); + } + + function log(bool p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); + } + + function log(bool p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); + } + + function log(address p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); + } + + function log(address p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); + } + + function log(address p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); + } + + function log(address p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); + } + + function log(uint256 p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); + } + + function log(string memory p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); + } + + function log(string memory p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); + } + + function log(string memory p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); + } + + function log(string memory p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); + } + + function log(bool p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); + } + + function log(bool p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); + } + + function log(bool p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); + } + + function log(bool p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); + } + + function log(bool p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); + } + + function log(bool p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); + } + + function log(bool p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); + } + + function log(bool p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); + } + + function log(address p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); + } + + function log(address p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); + } + + function log(address p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); + } + + function log(address p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); + } + + function log(address p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); + } + + function log(address p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); + } + + function log(address p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); + } + + function log(address p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); + } + + function log(address p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); + } + + function log(address p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); + } + + function log(address p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); + } + + function log(address p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); + } + +} \ No newline at end of file diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol new file mode 100644 index 0000000000..f7dd2b4106 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +import "./IERC165.sol"; + +/// @title ERC-1155 Multi Token Standard +/// @dev See https://eips.ethereum.org/EIPS/eip-1155 +/// Note: The ERC-165 identifier for this interface is 0xd9b67a26. +interface IERC1155 is IERC165 { + /// @dev + /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). + /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). + /// - The `_from` argument MUST be the address of the holder whose balance is decreased. + /// - The `_to` argument MUST be the address of the recipient whose balance is increased. + /// - The `_id` argument MUST be the token type being transferred. + /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. + /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). + /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). + event TransferSingle( + address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value + ); + + /// @dev + /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). + /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). + /// - The `_from` argument MUST be the address of the holder whose balance is decreased. + /// - The `_to` argument MUST be the address of the recipient whose balance is increased. + /// - The `_ids` argument MUST be the list of tokens being transferred. + /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by. + /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). + /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). + event TransferBatch( + address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values + ); + + /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled). + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + + /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986. + /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". + event URI(string _value, uint256 indexed _id); + + /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call). + /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). + /// - MUST revert if `_to` is the zero address. + /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent. + /// - MUST revert on any other error. + /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). + /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). + /// @param _from Source address + /// @param _to Target address + /// @param _id ID of the token type + /// @param _value Transfer amount + /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` + function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; + + /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). + /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). + /// - MUST revert if `_to` is the zero address. + /// - MUST revert if length of `_ids` is not the same as length of `_values`. + /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. + /// - MUST revert on any other error. + /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). + /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). + /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). + /// @param _from Source address + /// @param _to Target address + /// @param _ids IDs of each token type (order and length must match _values array) + /// @param _values Transfer amounts per token type (order and length must match _ids array) + /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` + function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data + ) external; + + /// @notice Get the balance of an account's tokens. + /// @param _owner The address of the token holder + /// @param _id ID of the token + /// @return The _owner's balance of the token type requested + function balanceOf(address _owner, uint256 _id) external view returns (uint256); + + /// @notice Get the balance of multiple account/token pairs + /// @param _owners The addresses of the token holders + /// @param _ids ID of the tokens + /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) + function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) + external + view + returns (uint256[] memory); + + /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. + /// @dev MUST emit the ApprovalForAll event on success. + /// @param _operator Address to add to the set of authorized operators + /// @param _approved True if the operator is approved, false to revoke approval + function setApprovalForAll(address _operator, bool _approved) external; + + /// @notice Queries the approval status of an operator for a given owner. + /// @param _owner The owner of the tokens + /// @param _operator Address of authorized operator + /// @return True if the operator is approved, false if not + function isApprovedForAll(address _owner, address _operator) external view returns (bool); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol new file mode 100644 index 0000000000..9af4bf800f --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +interface IERC165 { + /// @notice Query if a contract implements an interface + /// @param interfaceID The interface identifier, as specified in ERC-165 + /// @dev Interface identification is specified in ERC-165. This function + /// uses less than 30,000 gas. + /// @return `true` if the contract implements `interfaceID` and + /// `interfaceID` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol new file mode 100644 index 0000000000..ba40806c3b --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +/// @dev Interface of the ERC20 standard as defined in the EIP. +/// @dev This includes the optional name, symbol, and decimals metadata. +interface IERC20 { + /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). + event Transfer(address indexed from, address indexed to, uint256 value); + + /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` + /// is the new allowance. + event Approval(address indexed owner, address indexed spender, uint256 value); + + /// @notice Returns the amount of tokens in existence. + function totalSupply() external view returns (uint256); + + /// @notice Returns the amount of tokens owned by `account`. + function balanceOf(address account) external view returns (uint256); + + /// @notice Moves `amount` tokens from the caller's account to `to`. + function transfer(address to, uint256 amount) external returns (bool); + + /// @notice Returns the remaining number of tokens that `spender` is allowed + /// to spend on behalf of `owner` + function allowance(address owner, address spender) external view returns (uint256); + + /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. + /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + function approve(address spender, uint256 amount) external returns (bool); + + /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. + /// `amount` is then deducted from the caller's allowance. + function transferFrom(address from, address to, uint256 amount) external returns (bool); + + /// @notice Returns the name of the token. + function name() external view returns (string memory); + + /// @notice Returns the symbol of the token. + function symbol() external view returns (string memory); + + /// @notice Returns the decimals places of the token. + function decimals() external view returns (uint8); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol new file mode 100644 index 0000000000..bfe3a1155e --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +import "./IERC20.sol"; + +/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in +/// https://eips.ethereum.org/EIPS/eip-4626 +interface IERC4626 is IERC20 { + event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); + + event Withdraw( + address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares + ); + + /// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. + /// @dev + /// - MUST be an ERC-20 token contract. + /// - MUST NOT revert. + function asset() external view returns (address assetTokenAddress); + + /// @notice Returns the total amount of the underlying asset that is “managed” by Vault. + /// @dev + /// - SHOULD include any compounding that occurs from yield. + /// - MUST be inclusive of any fees that are charged against assets in the Vault. + /// - MUST NOT revert. + function totalAssets() external view returns (uint256 totalManagedAssets); + + /// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal + /// scenario where all the conditions are met. + /// @dev + /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. + /// - MUST NOT show any variations depending on the caller. + /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. + /// - MUST NOT revert. + /// + /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the + /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and + /// from. + function convertToShares(uint256 assets) external view returns (uint256 shares); + + /// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal + /// scenario where all the conditions are met. + /// @dev + /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. + /// - MUST NOT show any variations depending on the caller. + /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. + /// - MUST NOT revert. + /// + /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the + /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and + /// from. + function convertToAssets(uint256 shares) external view returns (uint256 assets); + + /// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, + /// through a deposit call. + /// @dev + /// - MUST return a limited value if receiver is subject to some deposit limit. + /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. + /// - MUST NOT revert. + function maxDeposit(address receiver) external view returns (uint256 maxAssets); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given + /// current on-chain conditions. + /// @dev + /// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit + /// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called + /// in the same transaction. + /// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the + /// deposit would be accepted, regardless if the user has enough tokens approved, etc. + /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by depositing. + function previewDeposit(uint256 assets) external view returns (uint256 shares); + + /// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. + /// @dev + /// - MUST emit the Deposit event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + /// deposit execution, and are accounted for during deposit. + /// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not + /// approving enough underlying tokens to the Vault contract, etc). + /// + /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. + function deposit(uint256 assets, address receiver) external returns (uint256 shares); + + /// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. + /// @dev + /// - MUST return a limited value if receiver is subject to some mint limit. + /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. + /// - MUST NOT revert. + function maxMint(address receiver) external view returns (uint256 maxShares); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given + /// current on-chain conditions. + /// @dev + /// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call + /// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the + /// same transaction. + /// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint + /// would be accepted, regardless if the user has enough tokens approved, etc. + /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by minting. + function previewMint(uint256 shares) external view returns (uint256 assets); + + /// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. + /// @dev + /// - MUST emit the Deposit event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint + /// execution, and are accounted for during mint. + /// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not + /// approving enough underlying tokens to the Vault contract, etc). + /// + /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. + function mint(uint256 shares, address receiver) external returns (uint256 assets); + + /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the + /// Vault, through a withdraw call. + /// @dev + /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. + /// - MUST NOT revert. + function maxWithdraw(address owner) external view returns (uint256 maxAssets); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, + /// given current on-chain conditions. + /// @dev + /// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw + /// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if + /// called + /// in the same transaction. + /// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though + /// the withdrawal would be accepted, regardless if the user has enough shares, etc. + /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by depositing. + function previewWithdraw(uint256 assets) external view returns (uint256 shares); + + /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver. + /// @dev + /// - MUST emit the Withdraw event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + /// withdraw execution, and are accounted for during withdraw. + /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner + /// not having enough shares, etc). + /// + /// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. + /// Those methods should be performed separately. + function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); + + /// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, + /// through a redeem call. + /// @dev + /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. + /// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. + /// - MUST NOT revert. + function maxRedeem(address owner) external view returns (uint256 maxShares); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, + /// given current on-chain conditions. + /// @dev + /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call + /// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the + /// same transaction. + /// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the + /// redemption would be accepted, regardless if the user has enough shares, etc. + /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by redeeming. + function previewRedeem(uint256 shares) external view returns (uint256 assets); + + /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver. + /// @dev + /// - MUST emit the Withdraw event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + /// redeem execution, and are accounted for during redeem. + /// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner + /// not having enough shares, etc). + /// + /// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. + /// Those methods should be performed separately. + function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol new file mode 100644 index 0000000000..0a16f45cc5 --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +import "./IERC165.sol"; + +/// @title ERC-721 Non-Fungible Token Standard +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x80ac58cd. +interface IERC721 is IERC165 { + /// @dev This emits when ownership of any NFT changes by any mechanism. + /// This event emits when NFTs are created (`from` == 0) and destroyed + /// (`to` == 0). Exception: during contract creation, any number of NFTs + /// may be created and assigned without emitting Transfer. At the time of + /// any transfer, the approved address for that NFT (if any) is reset to none. + event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); + + /// @dev This emits when the approved address for an NFT is changed or + /// reaffirmed. The zero address indicates there is no approved address. + /// When a Transfer event emits, this also indicates that the approved + /// address for that NFT (if any) is reset to none. + event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); + + /// @dev This emits when an operator is enabled or disabled for an owner. + /// The operator can manage all NFTs of the owner. + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + + /// @notice Count all NFTs assigned to an owner + /// @dev NFTs assigned to the zero address are considered invalid, and this + /// function throws for queries about the zero address. + /// @param _owner An address for whom to query the balance + /// @return The number of NFTs owned by `_owner`, possibly zero + function balanceOf(address _owner) external view returns (uint256); + + /// @notice Find the owner of an NFT + /// @dev NFTs assigned to zero address are considered invalid, and queries + /// about them do throw. + /// @param _tokenId The identifier for an NFT + /// @return The address of the owner of the NFT + function ownerOf(uint256 _tokenId) external view returns (address); + + /// @notice Transfers the ownership of an NFT from one address to another address + /// @dev Throws unless `msg.sender` is the current owner, an authorized + /// operator, or the approved address for this NFT. Throws if `_from` is + /// not the current owner. Throws if `_to` is the zero address. Throws if + /// `_tokenId` is not a valid NFT. When transfer is complete, this function + /// checks if `_to` is a smart contract (code size > 0). If so, it calls + /// `onERC721Received` on `_to` and throws if the return value is not + /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. + /// @param _from The current owner of the NFT + /// @param _to The new owner + /// @param _tokenId The NFT to transfer + /// @param data Additional data with no specified format, sent in call to `_to` + function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; + + /// @notice Transfers the ownership of an NFT from one address to another address + /// @dev This works identically to the other function with an extra data parameter, + /// except this function just sets data to "". + /// @param _from The current owner of the NFT + /// @param _to The new owner + /// @param _tokenId The NFT to transfer + function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; + + /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE + /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE + /// THEY MAY BE PERMANENTLY LOST + /// @dev Throws unless `msg.sender` is the current owner, an authorized + /// operator, or the approved address for this NFT. Throws if `_from` is + /// not the current owner. Throws if `_to` is the zero address. Throws if + /// `_tokenId` is not a valid NFT. + /// @param _from The current owner of the NFT + /// @param _to The new owner + /// @param _tokenId The NFT to transfer + function transferFrom(address _from, address _to, uint256 _tokenId) external payable; + + /// @notice Change or reaffirm the approved address for an NFT + /// @dev The zero address indicates there is no approved address. + /// Throws unless `msg.sender` is the current NFT owner, or an authorized + /// operator of the current owner. + /// @param _approved The new approved NFT controller + /// @param _tokenId The NFT to approve + function approve(address _approved, uint256 _tokenId) external payable; + + /// @notice Enable or disable approval for a third party ("operator") to manage + /// all of `msg.sender`'s assets + /// @dev Emits the ApprovalForAll event. The contract MUST allow + /// multiple operators per owner. + /// @param _operator Address to add to the set of authorized operators + /// @param _approved True if the operator is approved, false to revoke approval + function setApprovalForAll(address _operator, bool _approved) external; + + /// @notice Get the approved address for a single NFT + /// @dev Throws if `_tokenId` is not a valid NFT. + /// @param _tokenId The NFT to find the approved address for + /// @return The approved address for this NFT, or the zero address if there is none + function getApproved(uint256 _tokenId) external view returns (address); + + /// @notice Query if an address is an authorized operator for another address + /// @param _owner The address that owns the NFTs + /// @param _operator The address that acts on behalf of the owner + /// @return True if `_operator` is an approved operator for `_owner`, false otherwise + function isApprovedForAll(address _owner, address _operator) external view returns (bool); +} + +/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. +interface IERC721TokenReceiver { + /// @notice Handle the receipt of an NFT + /// @dev The ERC721 smart contract calls this function on the recipient + /// after a `transfer`. This function MAY throw to revert and reject the + /// transfer. Return of other than the magic value MUST result in the + /// transaction being reverted. + /// Note: the contract address is always the message sender. + /// @param _operator The address which called `safeTransferFrom` function + /// @param _from The address which previously owned the token + /// @param _tokenId The NFT identifier which is being transferred + /// @param _data Additional data with no specified format + /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + /// unless throwing + function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) + external + returns (bytes4); +} + +/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x5b5e139f. +interface IERC721Metadata is IERC721 { + /// @notice A descriptive name for a collection of NFTs in this contract + function name() external view returns (string memory _name); + + /// @notice An abbreviated name for NFTs in this contract + function symbol() external view returns (string memory _symbol); + + /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. + /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC + /// 3986. The URI may point to a JSON file that conforms to the "ERC721 + /// Metadata JSON Schema". + function tokenURI(uint256 _tokenId) external view returns (string memory); +} + +/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x780e9d63. +interface IERC721Enumerable is IERC721 { + /// @notice Count NFTs tracked by this contract + /// @return A count of valid NFTs tracked by this contract, where each one of + /// them has an assigned and queryable owner not equal to the zero address + function totalSupply() external view returns (uint256); + + /// @notice Enumerate valid NFTs + /// @dev Throws if `_index` >= `totalSupply()`. + /// @param _index A counter less than `totalSupply()` + /// @return The token identifier for the `_index`th NFT, + /// (sort order not specified) + function tokenByIndex(uint256 _index) external view returns (uint256); + + /// @notice Enumerate NFTs assigned to an owner + /// @dev Throws if `_index` >= `balanceOf(_owner)` or if + /// `_owner` is the zero address, representing invalid NFTs. + /// @param _owner An address where we are interested in NFTs owned by them + /// @param _index A counter less than `balanceOf(_owner)` + /// @return The token identifier for the `_index`th NFT assigned to `_owner`, + /// (sort order not specified) + function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol new file mode 100644 index 0000000000..0d031b71dc --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +interface IMulticall3 { + struct Call { + address target; + bytes callData; + } + + struct Call3 { + address target; + bool allowFailure; + bytes callData; + } + + struct Call3Value { + address target; + bool allowFailure; + uint256 value; + bytes callData; + } + + struct Result { + bool success; + bytes returnData; + } + + function aggregate(Call[] calldata calls) + external + payable + returns (uint256 blockNumber, bytes[] memory returnData); + + function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); + + function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); + + function blockAndAggregate(Call[] calldata calls) + external + payable + returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); + + function getBasefee() external view returns (uint256 basefee); + + function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); + + function getBlockNumber() external view returns (uint256 blockNumber); + + function getChainId() external view returns (uint256 chainid); + + function getCurrentBlockCoinbase() external view returns (address coinbase); + + function getCurrentBlockDifficulty() external view returns (uint256 difficulty); + + function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); + + function getCurrentBlockTimestamp() external view returns (uint256 timestamp); + + function getEthBalance(address addr) external view returns (uint256 balance); + + function getLastBlockHash() external view returns (bytes32 blockHash); + + function tryAggregate(bool requireSuccess, Call[] calldata calls) + external + payable + returns (Result[] memory returnData); + + function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) + external + payable + returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol b/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol new file mode 100644 index 0000000000..2a022fa34d --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {IERC20} from "../interfaces/IERC20.sol"; + +/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. +/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol +contract MockERC20 is IERC20 { + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string internal _name; + + string internal _symbol; + + uint8 internal _decimals; + + function name() external view override returns (string memory) { + return _name; + } + + function symbol() external view override returns (string memory) { + return _symbol; + } + + function decimals() external view override returns (uint8) { + return _decimals; + } + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal _totalSupply; + + mapping(address => uint256) internal _balanceOf; + + mapping(address => mapping(address => uint256)) internal _allowance; + + function totalSupply() external view override returns (uint256) { + return _totalSupply; + } + + function balanceOf(address owner) external view override returns (uint256) { + return _balanceOf[owner]; + } + + function allowance(address owner, address spender) external view override returns (uint256) { + return _allowance[owner][spender]; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + INITIALIZE + //////////////////////////////////////////////////////////////*/ + + /// @dev A bool to track whether the contract has been initialized. + bool private initialized; + + /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and + /// syntaxes, we add an initialization function that can be called only once. + function initialize(string memory name_, string memory symbol_, uint8 decimals_) public { + require(!initialized, "ALREADY_INITIALIZED"); + + _name = name_; + _symbol = symbol_; + _decimals = decimals_; + + INITIAL_CHAIN_ID = _pureChainId(); + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + + initialized = true; + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public virtual override returns (bool) { + _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount); + _balanceOf[to] = _add(_balanceOf[to], amount); + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount); + + _balanceOf[from] = _sub(_balanceOf[from], amount); + _balanceOf[to] = _add(_balanceOf[to], amount); + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) + public + virtual + { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + _allowance[recoveredAddress][spender] = value; + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { + return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view virtual returns (bytes32) { + return keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(_name)), + keccak256("1"), + _pureChainId(), + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal virtual { + _totalSupply = _add(_totalSupply, amount); + _balanceOf[to] = _add(_balanceOf[to], amount); + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal virtual { + _balanceOf[from] = _sub(_balanceOf[from], amount); + _totalSupply = _sub(_totalSupply, amount); + + emit Transfer(from, address(0), amount); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL SAFE MATH LOGIC + //////////////////////////////////////////////////////////////*/ + + function _add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "ERC20: addition overflow"); + return c; + } + + function _sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(a >= b, "ERC20: subtraction underflow"); + return a - b; + } + + /*////////////////////////////////////////////////////////////// + HELPERS + //////////////////////////////////////////////////////////////*/ + + // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no + // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We + // can't simply access the chain ID in a normal view or pure function because the solc View Pure + // Checker changed `chainid` from pure to view in 0.8.0. + function _viewChainId() private view returns (uint256 chainId) { + // Assembly required since `block.chainid` was introduced in 0.8.0. + assembly { + chainId := chainid() + } + + address(this); // Silence warnings in older Solc versions. + } + + function _pureChainId() private pure returns (uint256 chainId) { + function() internal view returns (uint256) fnIn = _viewChainId; + function() internal pure returns (uint256) pureChainId; + assembly { + pureChainId := fnIn + } + chainId = pureChainId(); + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol b/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol new file mode 100644 index 0000000000..f21151bb9b --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {IERC721Metadata} from "../interfaces/IERC721.sol"; + +/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. +/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol +contract MockERC721 is IERC721Metadata { + /*////////////////////////////////////////////////////////////// + METADATA STORAGE/LOGIC + //////////////////////////////////////////////////////////////*/ + + string internal _name; + + string internal _symbol; + + function name() external view override returns (string memory) { + return _name; + } + + function symbol() external view override returns (string memory) { + return _symbol; + } + + function tokenURI(uint256 id) public view virtual override returns (string memory) {} + + /*////////////////////////////////////////////////////////////// + ERC721 BALANCE/OWNER STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) internal _ownerOf; + + mapping(address => uint256) internal _balanceOf; + + function ownerOf(uint256 id) public view virtual override returns (address owner) { + require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); + } + + function balanceOf(address owner) public view virtual override returns (uint256) { + require(owner != address(0), "ZERO_ADDRESS"); + + return _balanceOf[owner]; + } + + /*////////////////////////////////////////////////////////////// + ERC721 APPROVAL STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) internal _getApproved; + + mapping(address => mapping(address => bool)) internal _isApprovedForAll; + + function getApproved(uint256 id) public view virtual override returns (address) { + return _getApproved[id]; + } + + function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { + return _isApprovedForAll[owner][operator]; + } + + /*////////////////////////////////////////////////////////////// + INITIALIZE + //////////////////////////////////////////////////////////////*/ + + /// @dev A bool to track whether the contract has been initialized. + bool private initialized; + + /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and + /// syntaxes, we add an initialization function that can be called only once. + function initialize(string memory name_, string memory symbol_) public { + require(!initialized, "ALREADY_INITIALIZED"); + + _name = name_; + _symbol = symbol_; + + initialized = true; + } + + /*////////////////////////////////////////////////////////////// + ERC721 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 id) public payable virtual override { + address owner = _ownerOf[id]; + + require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); + + _getApproved[id] = spender; + + emit Approval(owner, spender, id); + } + + function setApprovalForAll(address operator, bool approved) public virtual override { + _isApprovedForAll[msg.sender][operator] = approved; + + emit ApprovalForAll(msg.sender, operator, approved); + } + + function transferFrom(address from, address to, uint256 id) public payable virtual override { + require(from == _ownerOf[id], "WRONG_FROM"); + + require(to != address(0), "INVALID_RECIPIENT"); + + require( + msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id], + "NOT_AUTHORIZED" + ); + + // Underflow of the sender's balance is impossible because we check for + // ownership above and the recipient's balance can't realistically overflow. + _balanceOf[from]--; + + _balanceOf[to]++; + + _ownerOf[id] = to; + + delete _getApproved[id]; + + emit Transfer(from, to, id); + } + + function safeTransferFrom(address from, address to, uint256 id) public payable virtual override { + transferFrom(from, to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function safeTransferFrom(address from, address to, uint256 id, bytes memory data) + public + payable + virtual + override + { + transferFrom(from, to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + /*////////////////////////////////////////////////////////////// + ERC165 LOGIC + //////////////////////////////////////////////////////////////*/ + + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 + || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 + || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 id) internal virtual { + require(to != address(0), "INVALID_RECIPIENT"); + + require(_ownerOf[id] == address(0), "ALREADY_MINTED"); + + // Counter overflow is incredibly unrealistic. + + _balanceOf[to]++; + + _ownerOf[id] = to; + + emit Transfer(address(0), to, id); + } + + function _burn(uint256 id) internal virtual { + address owner = _ownerOf[id]; + + require(owner != address(0), "NOT_MINTED"); + + _balanceOf[owner]--; + + delete _ownerOf[id]; + + delete _getApproved[id]; + + emit Transfer(owner, address(0), id); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL SAFE MINT LOGIC + //////////////////////////////////////////////////////////////*/ + + function _safeMint(address to, uint256 id) internal virtual { + _mint(to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function _safeMint(address to, uint256 id, bytes memory data) internal virtual { + _mint(to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + /*////////////////////////////////////////////////////////////// + HELPERS + //////////////////////////////////////////////////////////////*/ + + function _isContract(address _addr) private view returns (bool) { + uint256 codeLength; + + // Assembly required for versions < 0.8.0 to check extcodesize. + assembly { + codeLength := extcodesize(_addr) + } + + return codeLength > 0; + } +} + +interface IERC721TokenReceiver { + function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4); +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol b/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol new file mode 100644 index 0000000000..5714d0902d --- /dev/null +++ b/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol @@ -0,0 +1,13248 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +/// @author philogy +/// @dev Code generated automatically by script. +library safeconsole { + uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67; + + // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374) + // for the view-to-pure log trick. + function _sendLogPayload(uint256 offset, uint256 size) private pure { + function(uint256, uint256) internal view fnIn = _sendLogPayloadView; + function(uint256, uint256) internal pure pureSendLogPayload; + assembly { + pureSendLogPayload := fnIn + } + pureSendLogPayload(offset, size); + } + + function _sendLogPayloadView(uint256 offset, uint256 size) private view { + assembly { + pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) + } + } + + function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { + function(uint256, uint256, uint256) internal view fnIn = _memcopyView; + function(uint256, uint256, uint256) internal pure pureMemcopy; + assembly { + pureMemcopy := fnIn + } + pureMemcopy(fromOffset, toOffset, length); + } + + function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { + assembly { + pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) + } + } + + function logMemory(uint256 offset, uint256 length) internal pure { + if (offset >= 0x60) { + // Sufficient memory before slice to prepare call header. + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(sub(offset, 0x60)) + m1 := mload(sub(offset, 0x40)) + m2 := mload(sub(offset, 0x20)) + // Selector of `logBytes(bytes)`. + mstore(sub(offset, 0x60), 0xe17bf956) + mstore(sub(offset, 0x40), 0x20) + mstore(sub(offset, 0x20), length) + } + _sendLogPayload(offset - 0x44, length + 0x44); + assembly { + mstore(sub(offset, 0x60), m0) + mstore(sub(offset, 0x40), m1) + mstore(sub(offset, 0x20), m2) + } + } else { + // Insufficient space, so copy slice forward, add header and reverse. + bytes32 m0; + bytes32 m1; + bytes32 m2; + uint256 endOffset = offset + length; + assembly { + m0 := mload(add(endOffset, 0x00)) + m1 := mload(add(endOffset, 0x20)) + m2 := mload(add(endOffset, 0x40)) + } + _memcopy(offset, offset + 0x60, length); + assembly { + // Selector of `logBytes(bytes)`. + mstore(add(offset, 0x00), 0xe17bf956) + mstore(add(offset, 0x20), 0x20) + mstore(add(offset, 0x40), length) + } + _sendLogPayload(offset + 0x1c, length + 0x44); + _memcopy(offset + 0x60, offset, length); + assembly { + mstore(add(endOffset, 0x00), m0) + mstore(add(endOffset, 0x20), m1) + mstore(add(endOffset, 0x40), m2) + } + } + } + + function log(address p0) internal pure { + bytes32 m0; + bytes32 m1; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + // Selector of `log(address)`. + mstore(0x00, 0x2c2ecbc2) + mstore(0x20, p0) + } + _sendLogPayload(0x1c, 0x24); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + } + } + + function log(bool p0) internal pure { + bytes32 m0; + bytes32 m1; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + // Selector of `log(bool)`. + mstore(0x00, 0x32458eed) + mstore(0x20, p0) + } + _sendLogPayload(0x1c, 0x24); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + } + } + + function log(uint256 p0) internal pure { + bytes32 m0; + bytes32 m1; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + // Selector of `log(uint256)`. + mstore(0x00, 0xf82c50f1) + mstore(0x20, p0) + } + _sendLogPayload(0x1c, 0x24); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + } + } + + function log(bytes32 p0) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(string)`. + mstore(0x00, 0x41304fac) + mstore(0x20, 0x20) + writeString(0x40, p0) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(address,address)`. + mstore(0x00, 0xdaf0d4aa) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(address p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(address,bool)`. + mstore(0x00, 0x75b605d3) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(address p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(address,uint256)`. + mstore(0x00, 0x8309e8a8) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(address p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,string)`. + mstore(0x00, 0x759f86bb) + mstore(0x20, p0) + mstore(0x40, 0x40) + writeString(0x60, p1) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(bool,address)`. + mstore(0x00, 0x853c4849) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(bool p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(bool,bool)`. + mstore(0x00, 0x2a110e83) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(bool p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(bool,uint256)`. + mstore(0x00, 0x399174d3) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(bool p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,string)`. + mstore(0x00, 0x8feac525) + mstore(0x20, p0) + mstore(0x40, 0x40) + writeString(0x60, p1) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(uint256,address)`. + mstore(0x00, 0x69276c86) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(uint256 p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(uint256,bool)`. + mstore(0x00, 0x1c9d7eb3) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(uint256 p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(uint256,uint256)`. + mstore(0x00, 0xf666715a) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(uint256 p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,string)`. + mstore(0x00, 0x643fd0df) + mstore(0x20, p0) + mstore(0x40, 0x40) + writeString(0x60, p1) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(string,address)`. + mstore(0x00, 0x319af333) + mstore(0x20, 0x40) + mstore(0x40, p1) + writeString(0x60, p0) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(string,bool)`. + mstore(0x00, 0xc3b55635) + mstore(0x20, 0x40) + mstore(0x40, p1) + writeString(0x60, p0) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(string,uint256)`. + mstore(0x00, 0xb60e72cc) + mstore(0x20, 0x40) + mstore(0x40, p1) + writeString(0x60, p0) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,string)`. + mstore(0x00, 0x4b5c4277) + mstore(0x20, 0x40) + mstore(0x40, 0x80) + writeString(0x60, p0) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,address,address)`. + mstore(0x00, 0x018c84c2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,address,bool)`. + mstore(0x00, 0xf2a66286) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,address,uint256)`. + mstore(0x00, 0x17fe6185) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,address,string)`. + mstore(0x00, 0x007150be) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,bool,address)`. + mstore(0x00, 0xf11699ed) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,bool,bool)`. + mstore(0x00, 0xeb830c92) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,bool,uint256)`. + mstore(0x00, 0x9c4f99fb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,bool,string)`. + mstore(0x00, 0x212255cc) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,uint256,address)`. + mstore(0x00, 0x7bc0d848) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,uint256,bool)`. + mstore(0x00, 0x678209a8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,uint256,uint256)`. + mstore(0x00, 0xb69bcaf6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,uint256,string)`. + mstore(0x00, 0xa1f2e8aa) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,string,address)`. + mstore(0x00, 0xf08744e8) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,string,bool)`. + mstore(0x00, 0xcf020fb1) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,string,uint256)`. + mstore(0x00, 0x67dd6ff1) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(address,string,string)`. + mstore(0x00, 0xfb772265) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, 0xa0) + writeString(0x80, p1) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bool p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,address,address)`. + mstore(0x00, 0xd2763667) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,address,bool)`. + mstore(0x00, 0x18c9c746) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,address,uint256)`. + mstore(0x00, 0x5f7b9afb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,address,string)`. + mstore(0x00, 0xde9a9270) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,bool,address)`. + mstore(0x00, 0x1078f68d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,bool,bool)`. + mstore(0x00, 0x50709698) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,bool,uint256)`. + mstore(0x00, 0x12f21602) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,bool,string)`. + mstore(0x00, 0x2555fa46) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,uint256,address)`. + mstore(0x00, 0x088ef9d2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,uint256,bool)`. + mstore(0x00, 0xe8defba9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,uint256,uint256)`. + mstore(0x00, 0x37103367) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,uint256,string)`. + mstore(0x00, 0xc3fc3970) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,string,address)`. + mstore(0x00, 0x9591b953) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,string,bool)`. + mstore(0x00, 0xdbb4c247) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,string,uint256)`. + mstore(0x00, 0x1093ee11) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(bool,string,string)`. + mstore(0x00, 0xb076847f) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, 0xa0) + writeString(0x80, p1) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(uint256 p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,address,address)`. + mstore(0x00, 0xbcfd9be0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,address,bool)`. + mstore(0x00, 0x9b6ec042) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,address,uint256)`. + mstore(0x00, 0x5a9b5ed5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,address,string)`. + mstore(0x00, 0x63cb41f9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,bool,address)`. + mstore(0x00, 0x35085f7b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,bool,bool)`. + mstore(0x00, 0x20718650) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,bool,uint256)`. + mstore(0x00, 0x20098014) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,bool,string)`. + mstore(0x00, 0x85775021) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,uint256,address)`. + mstore(0x00, 0x5c96b331) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,uint256,bool)`. + mstore(0x00, 0x4766da72) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,uint256,uint256)`. + mstore(0x00, 0xd1ed7a3c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,uint256,string)`. + mstore(0x00, 0x71d04af2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,string,address)`. + mstore(0x00, 0x7afac959) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,string,bool)`. + mstore(0x00, 0x4ceda75a) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,string,uint256)`. + mstore(0x00, 0x37aa7d4c) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(uint256,string,string)`. + mstore(0x00, 0xb115611f) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, 0xa0) + writeString(0x80, p1) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,address,address)`. + mstore(0x00, 0xfcec75e0) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,address,bool)`. + mstore(0x00, 0xc91d5ed4) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,address,uint256)`. + mstore(0x00, 0x0d26b925) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,address,string)`. + mstore(0x00, 0xe0e9ad4f) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, 0xa0) + writeString(0x80, p0) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,bool,address)`. + mstore(0x00, 0x932bbb38) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,bool,bool)`. + mstore(0x00, 0x850b7ad6) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,bool,uint256)`. + mstore(0x00, 0xc95958d6) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,bool,string)`. + mstore(0x00, 0xe298f47d) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, 0xa0) + writeString(0x80, p0) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,uint256,address)`. + mstore(0x00, 0x1c7ec448) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,uint256,bool)`. + mstore(0x00, 0xca7733b1) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,uint256,uint256)`. + mstore(0x00, 0xca47c4eb) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,uint256,string)`. + mstore(0x00, 0x5970e089) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, 0xa0) + writeString(0x80, p0) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,string,address)`. + mstore(0x00, 0x95ed0195) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, p2) + writeString(0x80, p0) + writeString(0xc0, p1) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,string,bool)`. + mstore(0x00, 0xb0e0f9b5) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, p2) + writeString(0x80, p0) + writeString(0xc0, p1) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,string,uint256)`. + mstore(0x00, 0x5821efa1) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, p2) + writeString(0x80, p0) + writeString(0xc0, p1) + } + _sendLogPayload(0x1c, 0xe4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + // Selector of `log(string,string,string)`. + mstore(0x00, 0x2ced7cef) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, 0xe0) + writeString(0x80, p0) + writeString(0xc0, p1) + writeString(0x100, p2) + } + _sendLogPayload(0x1c, 0x124); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + } + } + + function log(address p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,address,address)`. + mstore(0x00, 0x665bf134) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,address,bool)`. + mstore(0x00, 0x0e378994) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,address,uint256)`. + mstore(0x00, 0x94250d77) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,address,string)`. + mstore(0x00, 0xf808da20) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,bool,address)`. + mstore(0x00, 0x9f1bc36e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,bool,bool)`. + mstore(0x00, 0x2cd4134a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,bool,uint256)`. + mstore(0x00, 0x3971e78c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,bool,string)`. + mstore(0x00, 0xaa6540c8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,uint256,address)`. + mstore(0x00, 0x8da6def5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,uint256,bool)`. + mstore(0x00, 0x9b4254e2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,uint256,uint256)`. + mstore(0x00, 0xbe553481) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,uint256,string)`. + mstore(0x00, 0xfdb4f990) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,string,address)`. + mstore(0x00, 0x8f736d16) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,string,bool)`. + mstore(0x00, 0x6f1a594e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,string,uint256)`. + mstore(0x00, 0xef1cefe7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,address,string,string)`. + mstore(0x00, 0x21bdaf25) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,address,address)`. + mstore(0x00, 0x660375dd) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,address,bool)`. + mstore(0x00, 0xa6f50b0f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,address,uint256)`. + mstore(0x00, 0xa75c59de) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,address,string)`. + mstore(0x00, 0x2dd778e6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,bool,address)`. + mstore(0x00, 0xcf394485) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,bool,bool)`. + mstore(0x00, 0xcac43479) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,bool,uint256)`. + mstore(0x00, 0x8c4e5de6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,bool,string)`. + mstore(0x00, 0xdfc4a2e8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,uint256,address)`. + mstore(0x00, 0xccf790a1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,uint256,bool)`. + mstore(0x00, 0xc4643e20) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,uint256,uint256)`. + mstore(0x00, 0x386ff5f4) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,uint256,string)`. + mstore(0x00, 0x0aa6cfad) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,string,address)`. + mstore(0x00, 0x19fd4956) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,string,bool)`. + mstore(0x00, 0x50ad461d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,string,uint256)`. + mstore(0x00, 0x80e6a20b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,bool,string,string)`. + mstore(0x00, 0x475c5c33) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,address,address)`. + mstore(0x00, 0x478d1c62) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,address,bool)`. + mstore(0x00, 0xa1bcc9b3) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,address,uint256)`. + mstore(0x00, 0x100f650e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,address,string)`. + mstore(0x00, 0x1da986ea) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,bool,address)`. + mstore(0x00, 0xa31bfdcc) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,bool,bool)`. + mstore(0x00, 0x3bf5e537) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,bool,uint256)`. + mstore(0x00, 0x22f6b999) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,bool,string)`. + mstore(0x00, 0xc5ad85f9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,uint256,address)`. + mstore(0x00, 0x20e3984d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,uint256,bool)`. + mstore(0x00, 0x66f1bc67) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,uint256,uint256)`. + mstore(0x00, 0x34f0e636) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,uint256,string)`. + mstore(0x00, 0x4a28c017) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,string,address)`. + mstore(0x00, 0x5c430d47) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,string,bool)`. + mstore(0x00, 0xcf18105c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,string,uint256)`. + mstore(0x00, 0xbf01f891) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,uint256,string,string)`. + mstore(0x00, 0x88a8c406) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,address,address)`. + mstore(0x00, 0x0d36fa20) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,address,bool)`. + mstore(0x00, 0x0df12b76) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,address,uint256)`. + mstore(0x00, 0x457fe3cf) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,address,string)`. + mstore(0x00, 0xf7e36245) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,bool,address)`. + mstore(0x00, 0x205871c2) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,bool,bool)`. + mstore(0x00, 0x5f1d5c9f) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,bool,uint256)`. + mstore(0x00, 0x515e38b6) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,bool,string)`. + mstore(0x00, 0xbc0b61fe) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,uint256,address)`. + mstore(0x00, 0x63183678) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,uint256,bool)`. + mstore(0x00, 0x0ef7e050) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,uint256,uint256)`. + mstore(0x00, 0x1dc8e1b8) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,uint256,string)`. + mstore(0x00, 0x448830a8) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,string,address)`. + mstore(0x00, 0xa04e2f87) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,string,bool)`. + mstore(0x00, 0x35a5071f) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,string,uint256)`. + mstore(0x00, 0x159f8927) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(address,string,string,string)`. + mstore(0x00, 0x5d02c50b) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p1) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bool p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,address,address)`. + mstore(0x00, 0x1d14d001) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,address,bool)`. + mstore(0x00, 0x46600be0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,address,uint256)`. + mstore(0x00, 0x0c66d1be) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,address,string)`. + mstore(0x00, 0xd812a167) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,bool,address)`. + mstore(0x00, 0x1c41a336) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,bool,bool)`. + mstore(0x00, 0x6a9c478b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,bool,uint256)`. + mstore(0x00, 0x07831502) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,bool,string)`. + mstore(0x00, 0x4a66cb34) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,uint256,address)`. + mstore(0x00, 0x136b05dd) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,uint256,bool)`. + mstore(0x00, 0xd6019f1c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,uint256,uint256)`. + mstore(0x00, 0x7bf181a1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,uint256,string)`. + mstore(0x00, 0x51f09ff8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,string,address)`. + mstore(0x00, 0x6f7c603e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,string,bool)`. + mstore(0x00, 0xe2bfd60b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,string,uint256)`. + mstore(0x00, 0xc21f64c7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,address,string,string)`. + mstore(0x00, 0xa73c1db6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,address,address)`. + mstore(0x00, 0xf4880ea4) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,address,bool)`. + mstore(0x00, 0xc0a302d8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,address,uint256)`. + mstore(0x00, 0x4c123d57) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,address,string)`. + mstore(0x00, 0xa0a47963) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,bool,address)`. + mstore(0x00, 0x8c329b1a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,bool,bool)`. + mstore(0x00, 0x3b2a5ce0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,bool,uint256)`. + mstore(0x00, 0x6d7045c1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,bool,string)`. + mstore(0x00, 0x2ae408d4) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,uint256,address)`. + mstore(0x00, 0x54a7a9a0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,uint256,bool)`. + mstore(0x00, 0x619e4d0e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,uint256,uint256)`. + mstore(0x00, 0x0bb00eab) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,uint256,string)`. + mstore(0x00, 0x7dd4d0e0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,string,address)`. + mstore(0x00, 0xf9ad2b89) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,string,bool)`. + mstore(0x00, 0xb857163a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,string,uint256)`. + mstore(0x00, 0xe3a9ca2f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,bool,string,string)`. + mstore(0x00, 0x6d1e8751) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,address,address)`. + mstore(0x00, 0x26f560a8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,address,bool)`. + mstore(0x00, 0xb4c314ff) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,address,uint256)`. + mstore(0x00, 0x1537dc87) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,address,string)`. + mstore(0x00, 0x1bb3b09a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,bool,address)`. + mstore(0x00, 0x9acd3616) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,bool,bool)`. + mstore(0x00, 0xceb5f4d7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,bool,uint256)`. + mstore(0x00, 0x7f9bbca2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,bool,string)`. + mstore(0x00, 0x9143dbb1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,uint256,address)`. + mstore(0x00, 0x00dd87b9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,uint256,bool)`. + mstore(0x00, 0xbe984353) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,uint256,uint256)`. + mstore(0x00, 0x374bb4b2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,uint256,string)`. + mstore(0x00, 0x8e69fb5d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,string,address)`. + mstore(0x00, 0xfedd1fff) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,string,bool)`. + mstore(0x00, 0xe5e70b2b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,string,uint256)`. + mstore(0x00, 0x6a1199e2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,uint256,string,string)`. + mstore(0x00, 0xf5bc2249) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,address,address)`. + mstore(0x00, 0x2b2b18dc) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,address,bool)`. + mstore(0x00, 0x6dd434ca) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,address,uint256)`. + mstore(0x00, 0xa5cada94) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,address,string)`. + mstore(0x00, 0x12d6c788) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,bool,address)`. + mstore(0x00, 0x538e06ab) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,bool,bool)`. + mstore(0x00, 0xdc5e935b) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,bool,uint256)`. + mstore(0x00, 0x1606a393) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,bool,string)`. + mstore(0x00, 0x483d0416) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,uint256,address)`. + mstore(0x00, 0x1596a1ce) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,uint256,bool)`. + mstore(0x00, 0x6b0e5d53) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,uint256,uint256)`. + mstore(0x00, 0x28863fcb) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,uint256,string)`. + mstore(0x00, 0x1ad96de6) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,string,address)`. + mstore(0x00, 0x97d394d8) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,string,bool)`. + mstore(0x00, 0x1e4b87e5) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,string,uint256)`. + mstore(0x00, 0x7be0c3eb) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(bool,string,string,string)`. + mstore(0x00, 0x1762e32a) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p1) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(uint256 p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,address,address)`. + mstore(0x00, 0x2488b414) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,address,bool)`. + mstore(0x00, 0x091ffaf5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,address,uint256)`. + mstore(0x00, 0x736efbb6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,address,string)`. + mstore(0x00, 0x031c6f73) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,bool,address)`. + mstore(0x00, 0xef72c513) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,bool,bool)`. + mstore(0x00, 0xe351140f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,bool,uint256)`. + mstore(0x00, 0x5abd992a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,bool,string)`. + mstore(0x00, 0x90fb06aa) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,uint256,address)`. + mstore(0x00, 0x15c127b5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,uint256,bool)`. + mstore(0x00, 0x5f743a7c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,uint256,uint256)`. + mstore(0x00, 0x0c9cd9c1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,uint256,string)`. + mstore(0x00, 0xddb06521) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,string,address)`. + mstore(0x00, 0x9cba8fff) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,string,bool)`. + mstore(0x00, 0xcc32ab07) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,string,uint256)`. + mstore(0x00, 0x46826b5d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,address,string,string)`. + mstore(0x00, 0x3e128ca3) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,address,address)`. + mstore(0x00, 0xa1ef4cbb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,address,bool)`. + mstore(0x00, 0x454d54a5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,address,uint256)`. + mstore(0x00, 0x078287f5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,address,string)`. + mstore(0x00, 0xade052c7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,bool,address)`. + mstore(0x00, 0x69640b59) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,bool,bool)`. + mstore(0x00, 0xb6f577a1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,bool,uint256)`. + mstore(0x00, 0x7464ce23) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,bool,string)`. + mstore(0x00, 0xdddb9561) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,uint256,address)`. + mstore(0x00, 0x88cb6041) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,uint256,bool)`. + mstore(0x00, 0x91a02e2a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,uint256,uint256)`. + mstore(0x00, 0xc6acc7a8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,uint256,string)`. + mstore(0x00, 0xde03e774) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,string,address)`. + mstore(0x00, 0xef529018) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,string,bool)`. + mstore(0x00, 0xeb928d7f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,string,uint256)`. + mstore(0x00, 0x2c1d0746) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,bool,string,string)`. + mstore(0x00, 0x68c8b8bd) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,address,address)`. + mstore(0x00, 0x56a5d1b1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,address,bool)`. + mstore(0x00, 0x15cac476) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,address,uint256)`. + mstore(0x00, 0x88f6e4b2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,address,string)`. + mstore(0x00, 0x6cde40b8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,bool,address)`. + mstore(0x00, 0x9a816a83) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,bool,bool)`. + mstore(0x00, 0xab085ae6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,bool,uint256)`. + mstore(0x00, 0xeb7f6fd2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,bool,string)`. + mstore(0x00, 0xa5b4fc99) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,uint256,address)`. + mstore(0x00, 0xfa8185af) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,uint256,bool)`. + mstore(0x00, 0xc598d185) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,uint256,uint256)`. + mstore(0x00, 0x193fb800) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,uint256,string)`. + mstore(0x00, 0x59cfcbe3) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,string,address)`. + mstore(0x00, 0x42d21db7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,string,bool)`. + mstore(0x00, 0x7af6ab25) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,string,uint256)`. + mstore(0x00, 0x5da297eb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,uint256,string,string)`. + mstore(0x00, 0x27d8afd2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,address,address)`. + mstore(0x00, 0x6168ed61) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,address,bool)`. + mstore(0x00, 0x90c30a56) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,address,uint256)`. + mstore(0x00, 0xe8d3018d) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,address,string)`. + mstore(0x00, 0x9c3adfa1) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,bool,address)`. + mstore(0x00, 0xae2ec581) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,bool,bool)`. + mstore(0x00, 0xba535d9c) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,bool,uint256)`. + mstore(0x00, 0xcf009880) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,bool,string)`. + mstore(0x00, 0xd2d423cd) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,uint256,address)`. + mstore(0x00, 0x3b2279b4) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,uint256,bool)`. + mstore(0x00, 0x691a8f74) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,uint256,uint256)`. + mstore(0x00, 0x82c25b74) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,uint256,string)`. + mstore(0x00, 0xb7b914ca) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,string,address)`. + mstore(0x00, 0xd583c602) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,string,bool)`. + mstore(0x00, 0xb3a6b6bd) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,string,uint256)`. + mstore(0x00, 0xb028c9bd) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(uint256,string,string,string)`. + mstore(0x00, 0x21ad0683) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p1) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,address,address)`. + mstore(0x00, 0xed8f28f6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,address,bool)`. + mstore(0x00, 0xb59dbd60) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,address,uint256)`. + mstore(0x00, 0x8ef3f399) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,address,string)`. + mstore(0x00, 0x800a1c67) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,bool,address)`. + mstore(0x00, 0x223603bd) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,bool,bool)`. + mstore(0x00, 0x79884c2b) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,bool,uint256)`. + mstore(0x00, 0x3e9f866a) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,bool,string)`. + mstore(0x00, 0x0454c079) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,uint256,address)`. + mstore(0x00, 0x63fb8bc5) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,uint256,bool)`. + mstore(0x00, 0xfc4845f0) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,uint256,uint256)`. + mstore(0x00, 0xf8f51b1e) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,uint256,string)`. + mstore(0x00, 0x5a477632) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,string,address)`. + mstore(0x00, 0xaabc9a31) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,string,bool)`. + mstore(0x00, 0x5f15d28c) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,string,uint256)`. + mstore(0x00, 0x91d1112e) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,address,string,string)`. + mstore(0x00, 0x245986f2) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,address,address)`. + mstore(0x00, 0x33e9dd1d) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,address,bool)`. + mstore(0x00, 0x958c28c6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,address,uint256)`. + mstore(0x00, 0x5d08bb05) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,address,string)`. + mstore(0x00, 0x2d8e33a4) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,bool,address)`. + mstore(0x00, 0x7190a529) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,bool,bool)`. + mstore(0x00, 0x895af8c5) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,bool,uint256)`. + mstore(0x00, 0x8e3f78a9) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,bool,string)`. + mstore(0x00, 0x9d22d5dd) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,uint256,address)`. + mstore(0x00, 0x935e09bf) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,uint256,bool)`. + mstore(0x00, 0x8af7cf8a) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,uint256,uint256)`. + mstore(0x00, 0x64b5bb67) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,uint256,string)`. + mstore(0x00, 0x742d6ee7) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,string,address)`. + mstore(0x00, 0xe0625b29) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,string,bool)`. + mstore(0x00, 0x3f8a701d) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,string,uint256)`. + mstore(0x00, 0x24f91465) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,bool,string,string)`. + mstore(0x00, 0xa826caeb) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,address,address)`. + mstore(0x00, 0x5ea2b7ae) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,address,bool)`. + mstore(0x00, 0x82112a42) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,address,uint256)`. + mstore(0x00, 0x4f04fdc6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,address,string)`. + mstore(0x00, 0x9ffb2f93) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,bool,address)`. + mstore(0x00, 0xe0e95b98) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,bool,bool)`. + mstore(0x00, 0x354c36d6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,bool,uint256)`. + mstore(0x00, 0xe41b6f6f) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,bool,string)`. + mstore(0x00, 0xabf73a98) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,uint256,address)`. + mstore(0x00, 0xe21de278) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,uint256,bool)`. + mstore(0x00, 0x7626db92) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,uint256,uint256)`. + mstore(0x00, 0xa7a87853) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,uint256,string)`. + mstore(0x00, 0x854b3496) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,string,address)`. + mstore(0x00, 0x7c4632a4) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,string,bool)`. + mstore(0x00, 0x7d24491d) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,string,uint256)`. + mstore(0x00, 0xc67ea9d1) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,uint256,string,string)`. + mstore(0x00, 0x5ab84e1f) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,address,address)`. + mstore(0x00, 0x439c7bef) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,address,bool)`. + mstore(0x00, 0x5ccd4e37) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,address,uint256)`. + mstore(0x00, 0x7cc3c607) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,address,string)`. + mstore(0x00, 0xeb1bff80) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,bool,address)`. + mstore(0x00, 0xc371c7db) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,bool,bool)`. + mstore(0x00, 0x40785869) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,bool,uint256)`. + mstore(0x00, 0xd6aefad2) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,bool,string)`. + mstore(0x00, 0x5e84b0ea) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,uint256,address)`. + mstore(0x00, 0x1023f7b2) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,uint256,bool)`. + mstore(0x00, 0xc3a8a654) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,uint256,uint256)`. + mstore(0x00, 0xf45d7d2c) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,uint256,string)`. + mstore(0x00, 0x5d1a971a) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,string,address)`. + mstore(0x00, 0x6d572f44) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,string,bool)`. + mstore(0x00, 0x2c1754ed) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,string,uint256)`. + mstore(0x00, 0x8eafb02b) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + } + _sendLogPayload(0x1c, 0x144); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + bytes32 m11; + bytes32 m12; + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + m11 := mload(0x160) + m12 := mload(0x180) + // Selector of `log(string,string,string,string)`. + mstore(0x00, 0xde68f20a) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, 0x140) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + writeString(0x160, p3) + } + _sendLogPayload(0x1c, 0x184); + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + mstore(0x160, m11) + mstore(0x180, m12) + } + } +} diff --git a/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol b/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol index d57af4290c..e2ed900c04 100644 --- a/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol +++ b/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity ^0.8.4; import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; diff --git a/contracts/test/v0.8/L2EP/ArbitrumCrossDomainForwarder.test.ts b/contracts/test/v0.8/L2EP/ArbitrumCrossDomainForwarder.test.ts deleted file mode 100644 index 6b6d8abad1..0000000000 --- a/contracts/test/v0.8/L2EP/ArbitrumCrossDomainForwarder.test.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { - impersonateAs, - publicAbi, - toArbitrumL2AliasAddress, -} from '../../test-helpers/helpers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let crossdomainMessenger: SignerWithAddress -let newL1OwnerAddress: string -let newOwnerCrossdomainMessenger: SignerWithAddress -let forwarderFactory: ContractFactory -let greeterFactory: ContractFactory -let forwarder: Contract -let greeter: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - l1OwnerAddress = owner.address - newL1OwnerAddress = stranger.address - - // Contract factories - forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol:ArbitrumCrossDomainForwarder', - owner, - ) - greeterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Greeter.sol:Greeter', - owner, - ) -}) - -describe('ArbitrumCrossDomainForwarder', () => { - beforeEach(async () => { - // governor config - crossdomainMessenger = await impersonateAs( - toArbitrumL2AliasAddress(l1OwnerAddress), - ) - await owner.sendTransaction({ - to: crossdomainMessenger.address, - value: ethers.utils.parseEther('1.0'), - }) - newOwnerCrossdomainMessenger = await impersonateAs( - toArbitrumL2AliasAddress(newL1OwnerAddress), - ) - await owner.sendTransaction({ - to: newOwnerCrossdomainMessenger.address, - value: ethers.utils.parseEther('1.0'), - }) - - forwarder = await forwarderFactory.deploy(l1OwnerAddress) - greeter = await greeterFactory.deploy(forwarder.address) - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(forwarder, [ - 'typeAndVersion', - 'crossDomainMessenger', - 'forward', - 'l1Owner', - 'transferL1Ownership', - 'acceptL1Ownership', - // ConfirmedOwner methods: - 'owner', - 'transferOwnership', - 'acceptOwnership', - ]) - }) - - describe('#constructor', () => { - it('should set the owner correctly', async () => { - const response = await forwarder.owner() - assert.equal(response, owner.address) - }) - - it('should set the l1Owner correctly', async () => { - const response = await forwarder.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - - it('should set the crossdomain messenger correctly', async () => { - const response = await forwarder.crossDomainMessenger() - assert.equal(response, crossdomainMessenger.address) - }) - - it('should set the typeAndVersion correctly', async () => { - const response = await forwarder.typeAndVersion() - assert.equal(response, 'ArbitrumCrossDomainForwarder 1.0.0') - }) - }) - - describe('#forward', () => { - it('should not be callable by unknown address', async () => { - await expect( - forwarder.connect(stranger).forward(greeter.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - await forwarder - .connect(crossdomainMessenger) - .forward(greeter.address, setGreetingData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should revert when contract call reverts', async () => { - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [''], - ) - await expect( - forwarder - .connect(crossdomainMessenger) - .forward(greeter.address, setGreetingData), - ).to.be.revertedWith('Invalid greeting length') - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - forwarder.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should not be callable by L2 owner', async () => { - const forwarderOwner = await forwarder.owner() - assert.equal(forwarderOwner, owner.address) - - await expect( - forwarder.connect(owner).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await forwarder.l1Owner() - await expect( - forwarder - .connect(crossdomainMessenger) - .transferL1Ownership(newL1OwnerAddress), - ) - .to.emit(forwarder, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, newL1OwnerAddress) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await forwarder.l1Owner() - await expect( - forwarder - .connect(crossdomainMessenger) - .transferL1Ownership(ethers.constants.AddressZero), - ) - .to.emit(forwarder, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - await expect( - forwarder.connect(crossdomainMessenger).acceptL1Ownership(), - ).to.be.revertedWith('Must be proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await forwarder.l1Owner() - await forwarder - .connect(crossdomainMessenger) - .transferL1Ownership(newL1OwnerAddress) - await expect( - forwarder.connect(newOwnerCrossdomainMessenger).acceptL1Ownership(), - ) - .to.emit(forwarder, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, newL1OwnerAddress) - - const updatedL1Owner = await forwarder.l1Owner() - assert.equal(updatedL1Owner, newL1OwnerAddress) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/ArbitrumCrossDomainGovernor.test.ts b/contracts/test/v0.8/L2EP/ArbitrumCrossDomainGovernor.test.ts deleted file mode 100644 index 96e93e833e..0000000000 --- a/contracts/test/v0.8/L2EP/ArbitrumCrossDomainGovernor.test.ts +++ /dev/null @@ -1,365 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import etherslib, { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { - impersonateAs, - publicAbi, - stripHexPrefix, - toArbitrumL2AliasAddress, -} from '../../test-helpers/helpers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let crossdomainMessenger: SignerWithAddress -let newL1OwnerAddress: string -let newOwnerCrossdomainMessenger: SignerWithAddress -let governorFactory: ContractFactory -let greeterFactory: ContractFactory -let multisendFactory: ContractFactory -let governor: Contract -let greeter: Contract -let multisend: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - l1OwnerAddress = owner.address - newL1OwnerAddress = stranger.address - - // Contract factories - governorFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol:ArbitrumCrossDomainGovernor', - owner, - ) - greeterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Greeter.sol:Greeter', - owner, - ) - multisendFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MultiSend.sol:MultiSend', - owner, - ) -}) - -describe('ArbitrumCrossDomainGovernor', () => { - beforeEach(async () => { - // governor config - crossdomainMessenger = await impersonateAs( - toArbitrumL2AliasAddress(l1OwnerAddress), - ) - await owner.sendTransaction({ - to: crossdomainMessenger.address, - value: ethers.utils.parseEther('1.0'), - }) - newOwnerCrossdomainMessenger = await impersonateAs( - toArbitrumL2AliasAddress(newL1OwnerAddress), - ) - await owner.sendTransaction({ - to: newOwnerCrossdomainMessenger.address, - value: ethers.utils.parseEther('1.0'), - }) - - governor = await governorFactory.deploy(l1OwnerAddress) - greeter = await greeterFactory.deploy(governor.address) - multisend = await multisendFactory.deploy() - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(governor, [ - 'typeAndVersion', - 'crossDomainMessenger', - 'forward', - 'forwardDelegate', - 'l1Owner', - 'transferL1Ownership', - 'acceptL1Ownership', - // ConfirmedOwner methods: - 'owner', - 'transferOwnership', - 'acceptOwnership', - ]) - }) - - describe('#constructor', () => { - it('should set the owner correctly', async () => { - const response = await governor.owner() - assert.equal(response, owner.address) - }) - - it('should set the l1Owner correctly', async () => { - const response = await governor.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - - it('should set the crossdomain messenger correctly', async () => { - const response = await governor.crossDomainMessenger() - assert.equal(response, crossdomainMessenger.address) - }) - - it('should set the typeAndVersion correctly', async () => { - const response = await governor.typeAndVersion() - assert.equal(response, 'ArbitrumCrossDomainGovernor 1.0.0') - }) - }) - - describe('#forward', () => { - it('should not be callable by unknown address', async () => { - await expect( - governor.connect(stranger).forward(greeter.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger or owner') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - await governor - .connect(crossdomainMessenger) - .forward(greeter.address, setGreetingData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should be callable by L2 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - await governor.connect(owner).forward(greeter.address, setGreetingData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should revert when contract call reverts', async () => { - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [''], - ) - await expect( - governor - .connect(crossdomainMessenger) - .forward(greeter.address, setGreetingData), - ).to.be.revertedWith('Invalid greeting length') - }) - }) - - describe('#forwardDelegate', () => { - it('should not be callable by unknown address', async () => { - await expect( - governor.connect(stranger).forwardDelegate(multisend.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger or owner') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'bar', - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - await governor - .connect(crossdomainMessenger) - .forwardDelegate(multisend.address, multisendData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, 'bar') - }) - - it('should be callable by L2 owner', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'bar', - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - await governor - .connect(owner) - .forwardDelegate(multisend.address, multisendData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, 'bar') - }) - - it('should revert batch when one call fails', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - '', // should revert - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - await expect( - governor - .connect(crossdomainMessenger) - .forwardDelegate(multisend.address, multisendData), - ).to.be.revertedWith('Governor delegatecall reverted') - - const greeting = await greeter.greeting() - assert.equal(greeting, '') // Unchanged - }) - - it('should bubble up revert when contract call reverts', async () => { - const triggerRevertData = - greeterFactory.interface.encodeFunctionData('triggerRevert') - await expect( - governor - .connect(crossdomainMessenger) - .forwardDelegate(greeter.address, triggerRevertData), - ).to.be.revertedWith('Greeter: revert triggered') - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - governor.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should not be callable by L2 owner', async () => { - const governorOwner = await governor.owner() - assert.equal(governorOwner, owner.address) - - await expect( - governor.connect(owner).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await governor.l1Owner() - await expect( - governor - .connect(crossdomainMessenger) - .transferL1Ownership(newL1OwnerAddress), - ) - .to.emit(governor, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, newL1OwnerAddress) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await governor.l1Owner() - await expect( - governor - .connect(crossdomainMessenger) - .transferL1Ownership(ethers.constants.AddressZero), - ) - .to.emit(governor, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - await expect( - governor.connect(crossdomainMessenger).acceptL1Ownership(), - ).to.be.revertedWith('Must be proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await governor.l1Owner() - await governor - .connect(crossdomainMessenger) - .transferL1Ownership(newL1OwnerAddress) - await expect( - governor.connect(newOwnerCrossdomainMessenger).acceptL1Ownership(), - ) - .to.emit(governor, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, newL1OwnerAddress) - - const updatedL1Owner = await governor.l1Owner() - assert.equal(updatedL1Owner, newL1OwnerAddress) - }) - }) -}) - -// Multisend contract helpers - -/** - * Encodes an underlying transaction for the Multisend contract - * - * @param operation 0 for CALL, 1 for DELEGATECALL - * @param to tx target address - * @param value tx value - * @param data tx data - */ -export function encodeTxData( - operation: number, - to: string, - value: number, - data: string, -): string { - let dataBuffer = Buffer.from(stripHexPrefix(data), 'hex') - const types = ['uint8', 'address', 'uint256', 'uint256', 'bytes'] - const values = [operation, to, value, dataBuffer.length, dataBuffer] - let encoded = ethers.utils.solidityPack(types, values) - return stripHexPrefix(encoded) -} - -/** - * Encodes a Multisend call - * - * @param MultisendInterface Ethers Interface object of the Multisend contract - * @param transactions one or more transactions to include in the Multisend call - * @param to tx target address - * @param value tx value - * @param data tx data - */ -export function encodeMultisendData( - MultisendInterface: etherslib.utils.Interface, - transactions: { to: string; value: number; data: string }[], -): string { - let nestedTransactionData = '0x' - for (let transaction of transactions) { - nestedTransactionData += encodeTxData( - 0, - transaction.to, - transaction.value, - transaction.data, - ) - } - const encodedMultisendFnData = MultisendInterface.encodeFunctionData( - 'multiSend', - [nestedTransactionData], - ) - return encodedMultisendFnData -} diff --git a/contracts/test/v0.8/L2EP/ArbitrumSequencerUptimeFeed.test.ts b/contracts/test/v0.8/L2EP/ArbitrumSequencerUptimeFeed.test.ts deleted file mode 100644 index 28f36c9ca6..0000000000 --- a/contracts/test/v0.8/L2EP/ArbitrumSequencerUptimeFeed.test.ts +++ /dev/null @@ -1,405 +0,0 @@ -import { ethers, network } from 'hardhat' -import { BigNumber, Contract } from 'ethers' -import { expect } from 'chai' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' - -describe('ArbitrumSequencerUptimeFeed', () => { - let flags: Contract - let arbitrumSequencerUptimeFeed: Contract - let accessController: Contract - let uptimeFeedConsumer: Contract - let deployer: SignerWithAddress - let l1Owner: SignerWithAddress - let l2Messenger: SignerWithAddress - const gasUsedDeviation = 100 - - before(async () => { - const accounts = await ethers.getSigners() - deployer = accounts[0] - l1Owner = accounts[1] - const dummy = accounts[2] - const l2MessengerAddress = ethers.utils.getAddress( - BigNumber.from(l1Owner.address) - .add('0x1111000000000000000000000000000000001111') - .toHexString(), - ) - // Pretend we're on L2 - await network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [l2MessengerAddress], - }) - l2Messenger = await ethers.getSigner(l2MessengerAddress) - // Credit the L2 messenger with some ETH - await dummy.sendTransaction({ - to: l2Messenger.address, - value: (await dummy.getBalance()).sub(ethers.utils.parseEther('0.1')), - }) - }) - - beforeEach(async () => { - const accessControllerFactory = await ethers.getContractFactory( - 'src/v0.8/shared/access/SimpleWriteAccessController.sol:SimpleWriteAccessController', - deployer, - ) - accessController = await accessControllerFactory.deploy() - - const flagsHistoryFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/Flags.sol:Flags', - deployer, - ) - flags = await flagsHistoryFactory.deploy( - accessController.address, - accessController.address, - ) - await accessController.addAccess(flags.address) - - const arbitrumSequencerStatusRecorderFactory = - await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol:ArbitrumSequencerUptimeFeed', - deployer, - ) - arbitrumSequencerUptimeFeed = - await arbitrumSequencerStatusRecorderFactory.deploy( - flags.address, - l1Owner.address, - ) - // Required for ArbitrumSequencerUptimeFeed to raise/lower flags - await accessController.addAccess(arbitrumSequencerUptimeFeed.address) - // Required for ArbitrumSequencerUptimeFeed to read flags - await flags.addAccess(arbitrumSequencerUptimeFeed.address) - - // Deployer requires access to invoke initialize - await accessController.addAccess(deployer.address) - // Once ArbitrumSequencerUptimeFeed has access, we can initialise the 0th aggregator round - const initTx = await arbitrumSequencerUptimeFeed - .connect(deployer) - .initialize() - await expect(initTx).to.emit(arbitrumSequencerUptimeFeed, 'Initialized') - - // Mock consumer - const statusFeedConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/tests/FeedConsumer.sol:FeedConsumer', - deployer, - ) - uptimeFeedConsumer = await statusFeedConsumerFactory.deploy( - arbitrumSequencerUptimeFeed.address, - ) - }) - - describe('#updateStatus', () => { - it(`should update status when status has changed and incoming timestamp is newer than the latest`, async () => { - let timestamp = await arbitrumSequencerUptimeFeed.latestTimestamp() - let tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(1) - - // Submit another status update, same status, newer timestamp, should ignore - tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp.add(1000)) - await expect(tx).not.to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - await expect(tx).to.emit(arbitrumSequencerUptimeFeed, 'UpdateIgnored') - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal('1') - expect(await arbitrumSequencerUptimeFeed.latestTimestamp()).to.equal( - timestamp, - ) - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp.add(2000) - tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - await expect(tx) - .to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - .withArgs(0, 3 /** roundId */, timestamp) - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(0) - expect(await arbitrumSequencerUptimeFeed.latestTimestamp()).to.equal( - timestamp, - ) - }) - - it(`should update status when status has changed and incoming timestamp is the same as latest`, async () => { - const timestamp = await arbitrumSequencerUptimeFeed.latestTimestamp() - let tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(1) - - // Submit another status update, same status, same timestamp, should ignore - tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx).not.to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - await expect(tx).to.emit(arbitrumSequencerUptimeFeed, 'UpdateIgnored') - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal('1') - expect(await arbitrumSequencerUptimeFeed.latestTimestamp()).to.equal( - timestamp, - ) - - // Submit another status update, different status, same timestamp should update - tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - await expect(tx) - .to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - .withArgs(0, 3 /** roundId */, timestamp) - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(0) - expect(await arbitrumSequencerUptimeFeed.latestTimestamp()).to.equal( - timestamp, - ) - }) - - it('should ignore out-of-order updates', async () => { - const timestamp = ( - await arbitrumSequencerUptimeFeed.latestTimestamp() - ).add(10_000) - // Update status - let tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(1) - - // Update with different status, but stale timestamp, should be ignored - const staleTimestamp = timestamp.sub(1000) - tx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(false, staleTimestamp) - await expect(tx).to.not.emit(arbitrumSequencerUptimeFeed, 'AnswerUpdated') - await expect(tx).to.emit(arbitrumSequencerUptimeFeed, 'UpdateIgnored') - }) - }) - - describe('AggregatorV3Interface', () => { - it('should return valid answer from getRoundData and latestRoundData', async () => { - let [roundId, answer, startedAt, updatedAt, answeredInRound] = - await arbitrumSequencerUptimeFeed.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(updatedAt) // startedAt = updatedAt = timestamp - - // Submit status update with different status and newer timestamp, should update - const timestamp = (startedAt as BigNumber).add(1000) - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - ;[roundId, answer, startedAt, updatedAt, answeredInRound] = - await arbitrumSequencerUptimeFeed.getRoundData(2) - expect(roundId).to.equal(2) - expect(answer).to.equal(1) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(timestamp) - expect(updatedAt).to.equal(startedAt) - - // Check that last round is still returning the correct data - ;[roundId, answer, startedAt, updatedAt, answeredInRound] = - await arbitrumSequencerUptimeFeed.getRoundData(1) - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(updatedAt) - - // Assert latestRoundData corresponds to latest round id - expect(await arbitrumSequencerUptimeFeed.getRoundData(2)).to.deep.equal( - await arbitrumSequencerUptimeFeed.latestRoundData(), - ) - }) - - it('should return 0 from #getRoundData when round does not yet exist (future roundId)', async () => { - const [roundId, answer, startedAt, updatedAt, answeredInRound] = - await arbitrumSequencerUptimeFeed.getRoundData(2) - expect(roundId).to.equal(2) - expect(answer).to.equal(0) - expect(startedAt).to.equal(0) - expect(updatedAt).to.equal(0) - expect(answeredInRound).to.equal(2) - }) - }) - - describe('Protect reads on AggregatorV2V3Interface functions', () => { - it('should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted', async () => { - // Sanity - consumer is not whitelisted - expect(await arbitrumSequencerUptimeFeed.checkEnabled()).to.be.true - expect( - await arbitrumSequencerUptimeFeed.hasAccess( - uptimeFeedConsumer.address, - '0x00', - ), - ).to.be.false - - // Assert reads are not possible from consuming contract - await expect(uptimeFeedConsumer.latestAnswer()).to.be.revertedWith( - 'No access', - ) - await expect(uptimeFeedConsumer.latestRoundData()).to.be.revertedWith( - 'No access', - ) - }) - - it('should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted', async () => { - // Whitelist consumer - await arbitrumSequencerUptimeFeed.addAccess(uptimeFeedConsumer.address) - // Sanity - consumer is whitelisted - expect(await arbitrumSequencerUptimeFeed.checkEnabled()).to.be.true - expect( - await arbitrumSequencerUptimeFeed.hasAccess( - uptimeFeedConsumer.address, - '0x00', - ), - ).to.be.true - - // Assert reads are possible from consuming contract - expect(await uptimeFeedConsumer.latestAnswer()).to.be.equal('0') - const [roundId, answer] = await uptimeFeedConsumer.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - }) - }) - - describe('Gas costs', () => { - it('should consume a known amount of gas for updates @skip-coverage', async () => { - // Sanity - start at flag = 0 (`false`) - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(0) - let timestamp = await arbitrumSequencerUptimeFeed.latestTimestamp() - - // Gas for no update - timestamp = timestamp.add(1000) - const _noUpdateTx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - const noUpdateTx = await _noUpdateTx.wait(1) - // Assert no update - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(0) - expect(noUpdateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28300, - gasUsedDeviation, - ) - - // Gas for update - timestamp = timestamp.add(1000) - const _updateTx = await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - const updateTx = await _updateTx.wait(1) - // Assert update - expect(await arbitrumSequencerUptimeFeed.latestAnswer()).to.equal(1) - expect(updateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 93015, - gasUsedDeviation, - ) - }) - - describe('Aggregator interface', () => { - beforeEach(async () => { - const timestamp = ( - await arbitrumSequencerUptimeFeed.latestTimestamp() - ).add(1000) - // Initialise a round - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - }) - - it('should consume a known amount of gas for getRoundData(uint80) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.getRoundData(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 31157, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestRoundData() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestRoundData(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28523, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestAnswer() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestAnswer(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28329, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestTimestamp() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestTimestamp(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28229, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestRound() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestRound(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28245, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for getAnswer(roundId) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.getAnswer(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30799, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for getTimestamp(roundId) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await arbitrumSequencerUptimeFeed - .connect(l2Messenger) - .populateTransaction.getTimestamp(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30753, - gasUsedDeviation, - ) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/ArbitrumValidator.test.ts b/contracts/test/v0.8/L2EP/ArbitrumValidator.test.ts deleted file mode 100644 index 232eea9583..0000000000 --- a/contracts/test/v0.8/L2EP/ArbitrumValidator.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber, BigNumberish, Contract, ContractFactory } from 'ethers' -import { expect } from 'chai' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { - deployMockContract, - MockContract, -} from '@ethereum-waffle/mock-contract' -/// Pick ABIs from compilation -// @ts-ignore -import { abi as arbitrumSequencerStatusRecorderAbi } from '../../../artifacts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol/ArbitrumSequencerUptimeFeed.json' -// @ts-ignore -import { abi as arbitrumInboxAbi } from '../../../artifacts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol/IInbox.json' -// @ts-ignore -import { abi as aggregatorAbi } from '../../../artifacts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol/AggregatorV2V3Interface.json' - -const truncateBigNumToAddress = (num: BigNumberish) => { - // Pad, then slice off '0x' prefix - const hexWithoutPrefix = BigNumber.from(num).toHexString().slice(2) - // Ethereum address is 20B -> 40 hex chars w/o 0x prefix - const truncated = hexWithoutPrefix - .split('') - .reverse() - .slice(0, 40) - .reverse() - .join('') - return '0x' + truncated -} - -describe('ArbitrumValidator', () => { - const MAX_GAS = BigNumber.from(1_000_000) - const GAS_PRICE_BID = BigNumber.from(1_000_000) - const BASE_FEE = BigNumber.from(14_000_000_000) - /** Fake L2 target */ - const L2_SEQ_STATUS_RECORDER_ADDRESS = - '0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b' - let arbitrumValidator: Contract - let accessController: Contract - let arbitrumSequencerStatusRecorderFactory: ContractFactory - let mockArbitrumInbox: Contract - let l1GasFeed: MockContract - let deployer: SignerWithAddress - let eoaValidator: SignerWithAddress - let arbitrumValidatorL2Address: string - before(async () => { - const accounts = await ethers.getSigners() - deployer = accounts[0] - eoaValidator = accounts[1] - }) - - beforeEach(async () => { - const accessControllerFactory = await ethers.getContractFactory( - 'src/v0.8/shared/access/SimpleWriteAccessController.sol:SimpleWriteAccessController', - deployer, - ) - accessController = await accessControllerFactory.deploy() - - // Required for building the calldata - arbitrumSequencerStatusRecorderFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol:ArbitrumSequencerUptimeFeed', - deployer, - ) - l1GasFeed = await deployMockContract(deployer as any, aggregatorAbi) - await l1GasFeed.mock.latestRoundData.returns( - '73786976294838220258' /** roundId */, - '96800000000' /** answer */, - '163826896' /** startedAt */, - '1638268960' /** updatedAt */, - '73786976294838220258' /** answeredInRound */, - ) - // Arbitrum Inbox contract on L1 - const mockArbitrumInboxFactory = await ethers.getContractFactory( - 'src/v0.8/tests/MockArbitrumInbox.sol:MockArbitrumInbox', - ) - mockArbitrumInbox = await mockArbitrumInboxFactory.deploy() - - // Contract under test - const arbitrumValidatorFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol:ArbitrumValidator', - deployer, - ) - arbitrumValidator = await arbitrumValidatorFactory.deploy( - mockArbitrumInbox.address, - L2_SEQ_STATUS_RECORDER_ADDRESS, - accessController.address, - MAX_GAS /** L1 gas bid */, - GAS_PRICE_BID /** L2 gas bid */, - BASE_FEE, - l1GasFeed.address, - 0, - ) - // Transfer some ETH to the ArbitrumValidator contract - await deployer.sendTransaction({ - to: arbitrumValidator.address, - value: ethers.utils.parseEther('1.0'), - }) - arbitrumValidatorL2Address = ethers.utils.getAddress( - truncateBigNumToAddress( - BigNumber.from(arbitrumValidator.address).add( - '0x1111000000000000000000000000000000001111', - ), - ), - ) - }) - - describe('#validate', () => { - it('post sequencer offline', async () => { - await arbitrumValidator.addAccess(eoaValidator.address) - - const now = Math.ceil(Date.now() / 1000) + 1000 - await ethers.provider.send('evm_setNextBlockTimestamp', [now]) - const arbitrumSequencerStatusRecorderCallData = - arbitrumSequencerStatusRecorderFactory.interface.encodeFunctionData( - 'updateStatus', - [true, now], - ) - await expect(arbitrumValidator.connect(eoaValidator).validate(0, 0, 1, 1)) - .to.emit( - mockArbitrumInbox, - 'RetryableTicketNoRefundAliasRewriteCreated', - ) - .withArgs( - L2_SEQ_STATUS_RECORDER_ADDRESS, - 0, - '25312000000000', - arbitrumValidatorL2Address, - arbitrumValidatorL2Address, - MAX_GAS, - GAS_PRICE_BID, - arbitrumSequencerStatusRecorderCallData, - ) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/CrossDomainOwnable.test.ts b/contracts/test/v0.8/L2EP/CrossDomainOwnable.test.ts deleted file mode 100644 index 7d9d58cfba..0000000000 --- a/contracts/test/v0.8/L2EP/CrossDomainOwnable.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let ownableFactory: ContractFactory -let ownable: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - l1OwnerAddress = owner.address - - // Contract factories - ownableFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/CrossDomainOwnable.sol:CrossDomainOwnable', - owner, - ) -}) - -describe('CrossDomainOwnable', () => { - beforeEach(async () => { - ownable = await ownableFactory.deploy(l1OwnerAddress) - }) - - describe('#constructor', () => { - it('should set the l1Owner correctly', async () => { - const response = await ownable.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - ownable.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Only callable by L1 owner') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await ownable.l1Owner() - await expect(ownable.transferL1Ownership(stranger.address)) - .to.emit(ownable, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, stranger.address) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await ownable.l1Owner() - await expect(ownable.transferL1Ownership(ethers.constants.AddressZero)) - .to.emit(ownable, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - await expect( - ownable.connect(stranger).acceptL1Ownership(), - ).to.be.revertedWith('Only callable by proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await ownable.l1Owner() - await ownable.transferL1Ownership(stranger.address) - await expect(ownable.connect(stranger).acceptL1Ownership()) - .to.emit(ownable, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, stranger.address) - - const updatedL1Owner = await ownable.l1Owner() - assert.equal(updatedL1Owner, stranger.address) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/OptimismCrossDomainForwarder.test.ts b/contracts/test/v0.8/L2EP/OptimismCrossDomainForwarder.test.ts deleted file mode 100644 index 3b75b412bf..0000000000 --- a/contracts/test/v0.8/L2EP/OptimismCrossDomainForwarder.test.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { publicAbi } from '../../test-helpers/helpers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let newL1OwnerAddress: string -let forwarderFactory: ContractFactory -let greeterFactory: ContractFactory -let crossDomainMessengerFactory: ContractFactory -let crossDomainMessenger: Contract -let forwarder: Contract -let greeter: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - - // forwarder config - l1OwnerAddress = owner.address - newL1OwnerAddress = stranger.address - - // Contract factories - forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol:OptimismCrossDomainForwarder', - owner, - ) - greeterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Greeter.sol:Greeter', - owner, - ) - crossDomainMessengerFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MockOVMCrossDomainMessenger.sol:MockOVMCrossDomainMessenger', - ) -}) - -describe('OptimismCrossDomainForwarder', () => { - beforeEach(async () => { - crossDomainMessenger = - await crossDomainMessengerFactory.deploy(l1OwnerAddress) - forwarder = await forwarderFactory.deploy( - crossDomainMessenger.address, - l1OwnerAddress, - ) - greeter = await greeterFactory.deploy(forwarder.address) - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(forwarder, [ - 'typeAndVersion', - 'crossDomainMessenger', - 'forward', - 'l1Owner', - 'transferL1Ownership', - 'acceptL1Ownership', - // ConfirmedOwner methods: - 'owner', - 'transferOwnership', - 'acceptOwnership', - ]) - }) - - describe('#constructor', () => { - it('should set the owner correctly', async () => { - const response = await forwarder.owner() - assert.equal(response, owner.address) - }) - - it('should set the l1Owner correctly', async () => { - const response = await forwarder.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - - it('should set the crossdomain messenger correctly', async () => { - const response = await forwarder.crossDomainMessenger() - assert.equal(response, crossDomainMessenger.address) - }) - - it('should set the typeAndVersion correctly', async () => { - const response = await forwarder.typeAndVersion() - assert.equal(response, 'OptimismCrossDomainForwarder 1.0.0') - }) - }) - - describe('#forward', () => { - it('should not be callable by unknown address', async () => { - await expect( - forwarder.connect(stranger).forward(greeter.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardData, 0) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should revert when contract call reverts', async () => { - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [''], - ) - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardData, 0), - ).to.be.revertedWith('Invalid greeting length') - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - forwarder.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should not be callable by L2 owner', async () => { - const forwarderOwner = await forwarder.owner() - assert.equal(forwarderOwner, owner.address) - - await expect( - forwarder.connect(owner).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await forwarder.l1Owner() - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardData, 0), - ) - .to.emit(forwarder, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, newL1OwnerAddress) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await forwarder.l1Owner() - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [ethers.constants.AddressZero], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardData, 0), - ) - .to.emit(forwarder, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardData, 0), - ).to.be.revertedWith('Must be proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await forwarder.l1Owner() - - // Transfer ownership - const forwardTransferData = forwarderFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - await crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardTransferData, 0) - - const forwardAcceptData = forwarderFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - // Simulate cross-chain message from another sender - await crossDomainMessenger._setMockMessageSender(newL1OwnerAddress) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(forwarder.address, forwardAcceptData, 0), - ) - .to.emit(forwarder, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, newL1OwnerAddress) - - const updatedL1Owner = await forwarder.l1Owner() - assert.equal(updatedL1Owner, newL1OwnerAddress) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/OptimismCrossDomainGovernor.test.ts b/contracts/test/v0.8/L2EP/OptimismCrossDomainGovernor.test.ts deleted file mode 100644 index 7fbd0f9aa2..0000000000 --- a/contracts/test/v0.8/L2EP/OptimismCrossDomainGovernor.test.ts +++ /dev/null @@ -1,409 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import etherslib, { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { publicAbi, stripHexPrefix } from '../../test-helpers/helpers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let newL1OwnerAddress: string -let governorFactory: ContractFactory -let greeterFactory: ContractFactory -let multisendFactory: ContractFactory -let crossDomainMessengerFactory: ContractFactory -let crossDomainMessenger: Contract -let governor: Contract -let greeter: Contract -let multisend: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - - // governor config - l1OwnerAddress = owner.address - newL1OwnerAddress = stranger.address - - // Contract factories - governorFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol:OptimismCrossDomainGovernor', - owner, - ) - greeterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Greeter.sol:Greeter', - owner, - ) - multisendFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MultiSend.sol:MultiSend', - owner, - ) - crossDomainMessengerFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MockOVMCrossDomainMessenger.sol:MockOVMCrossDomainMessenger', - ) -}) - -describe('OptimismCrossDomainGovernor', () => { - beforeEach(async () => { - crossDomainMessenger = - await crossDomainMessengerFactory.deploy(l1OwnerAddress) - governor = await governorFactory.deploy( - crossDomainMessenger.address, - l1OwnerAddress, - ) - greeter = await greeterFactory.deploy(governor.address) - multisend = await multisendFactory.deploy() - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(governor, [ - 'typeAndVersion', - 'crossDomainMessenger', - 'forward', - 'forwardDelegate', - 'l1Owner', - 'transferL1Ownership', - 'acceptL1Ownership', - // ConfirmedOwner methods: - 'owner', - 'transferOwnership', - 'acceptOwnership', - ]) - }) - - describe('#constructor', () => { - it('should set the owner correctly', async () => { - const response = await governor.owner() - assert.equal(response, owner.address) - }) - - it('should set the l1Owner correctly', async () => { - const response = await governor.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - - it('should set the crossdomain messenger correctly', async () => { - const response = await governor.crossDomainMessenger() - assert.equal(response, crossDomainMessenger.address) - }) - - it('should set the typeAndVersion correctly', async () => { - const response = await governor.typeAndVersion() - assert.equal(response, 'OptimismCrossDomainGovernor 1.0.0') - }) - }) - - describe('#forward', () => { - it('should not be callable by unknown address', async () => { - await expect( - governor.connect(stranger).forward(greeter.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger or owner') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should be callable by L2 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - await governor.connect(owner).forward(greeter.address, setGreetingData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should revert when contract call reverts', async () => { - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [''], - ) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0), - ).to.be.revertedWith('Invalid greeting length') - }) - }) - - describe('#forwardDelegate', () => { - it('should not be callable by unknown address', async () => { - await expect( - governor.connect(stranger).forwardDelegate(multisend.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger or owner') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'bar', - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forwardDelegate', - [multisend.address, multisendData], - ) - - await crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, 'bar') - }) - - it('should be callable by L2 owner', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'bar', - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - await governor - .connect(owner) - .forwardDelegate(multisend.address, multisendData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, 'bar') - }) - - it('should revert batch when one call fails', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - '', // should revert - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forwardDelegate', - [multisend.address, multisendData], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0), - ).to.be.revertedWith('Governor delegatecall reverted') - - const greeting = await greeter.greeting() - assert.equal(greeting, '') // Unchanged - }) - - it('should bubble up revert when contract call reverts', async () => { - const triggerRevertData = - greeterFactory.interface.encodeFunctionData('triggerRevert') - const forwardData = governorFactory.interface.encodeFunctionData( - 'forwardDelegate', - [greeter.address, triggerRevertData], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0), - ).to.be.revertedWith('Greeter: revert triggered') - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - governor.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should not be callable by L2 owner', async () => { - const governorOwner = await governor.owner() - assert.equal(governorOwner, owner.address) - - await expect( - governor.connect(owner).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await governor.l1Owner() - const forwardData = governorFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0), - ) - .to.emit(governor, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, newL1OwnerAddress) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await governor.l1Owner() - const forwardData = governorFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [ethers.constants.AddressZero], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0), - ) - .to.emit(governor, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - const forwardData = governorFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardData, 0), - ).to.be.revertedWith('Must be proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await governor.l1Owner() - - // Transfer ownership - const forwardTransferData = governorFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - await crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardTransferData, 0) - - const forwardAcceptData = governorFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - // Simulate cross-chain message from another sender - await crossDomainMessenger._setMockMessageSender(newL1OwnerAddress) - - await expect( - crossDomainMessenger // Simulate cross-chain OVM message - .connect(stranger) - .sendMessage(governor.address, forwardAcceptData, 0), - ) - .to.emit(governor, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, newL1OwnerAddress) - - const updatedL1Owner = await governor.l1Owner() - assert.equal(updatedL1Owner, newL1OwnerAddress) - }) - }) -}) - -// Multisend contract helpers - -/** - * Encodes an underlying transaction for the Multisend contract - * - * @param operation 0 for CALL, 1 for DELEGATECALL - * @param to tx target address - * @param value tx value - * @param data tx data - */ -export function encodeTxData( - operation: number, - to: string, - value: number, - data: string, -): string { - let dataBuffer = Buffer.from(stripHexPrefix(data), 'hex') - const types = ['uint8', 'address', 'uint256', 'uint256', 'bytes'] - const values = [operation, to, value, dataBuffer.length, dataBuffer] - let encoded = ethers.utils.solidityPack(types, values) - return stripHexPrefix(encoded) -} - -/** - * Encodes a Multisend call - * - * @param MultisendInterface Ethers Interface object of the Multisend contract - * @param transactions one or more transactions to include in the Multisend call - * @param to tx target address - * @param value tx value - * @param data tx data - */ -export function encodeMultisendData( - MultisendInterface: etherslib.utils.Interface, - transactions: { to: string; value: number; data: string }[], -): string { - let nestedTransactionData = '0x' - for (let transaction of transactions) { - nestedTransactionData += encodeTxData( - 0, - transaction.to, - transaction.value, - transaction.data, - ) - } - const encodedMultisendFnData = MultisendInterface.encodeFunctionData( - 'multiSend', - [nestedTransactionData], - ) - return encodedMultisendFnData -} diff --git a/contracts/test/v0.8/L2EP/OptimismSequencerUptimeFeed.test.ts b/contracts/test/v0.8/L2EP/OptimismSequencerUptimeFeed.test.ts deleted file mode 100644 index 32e17b1077..0000000000 --- a/contracts/test/v0.8/L2EP/OptimismSequencerUptimeFeed.test.ts +++ /dev/null @@ -1,426 +0,0 @@ -import { ethers, network } from 'hardhat' -import { BigNumber, Contract } from 'ethers' -import { expect } from 'chai' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' - -describe('OptimismSequencerUptimeFeed', () => { - let l2CrossDomainMessenger: Contract - let optimismUptimeFeed: Contract - let uptimeFeedConsumer: Contract - let deployer: SignerWithAddress - let l1Owner: SignerWithAddress - let l2Messenger: SignerWithAddress - let dummy: SignerWithAddress - const gasUsedDeviation = 100 - const initialStatus = 0 - - before(async () => { - const accounts = await ethers.getSigners() - deployer = accounts[0] - l1Owner = accounts[1] - dummy = accounts[3] - - const l2CrossDomainMessengerFactory = await ethers.getContractFactory( - 'src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol:MockOptimismL2CrossDomainMessenger', - deployer, - ) - - l2CrossDomainMessenger = await l2CrossDomainMessengerFactory.deploy() - - // Pretend we're on L2 - await network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [l2CrossDomainMessenger.address], - }) - l2Messenger = await ethers.getSigner(l2CrossDomainMessenger.address) - // Credit the L2 messenger with some ETH - await dummy.sendTransaction({ - to: l2Messenger.address, - value: ethers.utils.parseEther('10'), - }) - }) - - beforeEach(async () => { - const optimismSequencerStatusRecorderFactory = - await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol:OptimismSequencerUptimeFeed', - deployer, - ) - optimismUptimeFeed = await optimismSequencerStatusRecorderFactory.deploy( - l1Owner.address, - l2CrossDomainMessenger.address, - initialStatus, - ) - - // Set mock sender in mock L2 messenger contract - await l2CrossDomainMessenger.setSender(l1Owner.address) - - // Mock consumer - const statusFeedConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/tests/FeedConsumer.sol:FeedConsumer', - deployer, - ) - uptimeFeedConsumer = await statusFeedConsumerFactory.deploy( - optimismUptimeFeed.address, - ) - }) - - describe('constructor', () => { - it('should have been deployed with the correct initial state', async () => { - const l1Sender = await optimismUptimeFeed.l1Sender() - expect(l1Sender).to.equal(l1Owner.address) - const { roundId, answer } = await optimismUptimeFeed.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(initialStatus) - }) - }) - - describe('#updateStatus', () => { - it('should revert if called by an address that is not the L2 Cross Domain Messenger', async () => { - let timestamp = await optimismUptimeFeed.latestTimestamp() - expect( - optimismUptimeFeed.connect(dummy).updateStatus(true, timestamp), - ).to.be.revertedWith('InvalidSender') - }) - - it('should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender', async () => { - let timestamp = await optimismUptimeFeed.latestTimestamp() - await l2CrossDomainMessenger.setSender(dummy.address) - expect( - optimismUptimeFeed.connect(dummy).updateStatus(true, timestamp), - ).to.be.revertedWith('InvalidSender') - }) - - it(`should update status when status has not changed and incoming timestamp is the same as latest`, async () => { - const timestamp = await optimismUptimeFeed.latestTimestamp() - let tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(optimismUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(1) - - const latestRoundBeforeUpdate = await optimismUptimeFeed.latestRoundData() - - tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp.add(200)) - - // Submit another status update with the same status - const latestBlock = await ethers.provider.getBlock('latest') - - await expect(tx) - .to.emit(optimismUptimeFeed, 'RoundUpdated') - .withArgs(1, latestBlock.timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(1) - expect(await optimismUptimeFeed.latestTimestamp()).to.equal(timestamp) - - // Verify that latest round has been properly updated - const latestRoundDataAfterUpdate = - await optimismUptimeFeed.latestRoundData() - expect(latestRoundDataAfterUpdate.roundId).to.equal( - latestRoundBeforeUpdate.roundId, - ) - expect(latestRoundDataAfterUpdate.answer).to.equal( - latestRoundBeforeUpdate.answer, - ) - expect(latestRoundDataAfterUpdate.startedAt).to.equal( - latestRoundBeforeUpdate.startedAt, - ) - expect(latestRoundDataAfterUpdate.answeredInRound).to.equal( - latestRoundBeforeUpdate.answeredInRound, - ) - expect(latestRoundDataAfterUpdate.updatedAt).to.equal( - latestBlock.timestamp, - ) - }) - - it(`should update status when status has changed and incoming timestamp is newer than the latest`, async () => { - let timestamp = await optimismUptimeFeed.latestTimestamp() - let tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(optimismUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(1) - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp.add(2000) - tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - await expect(tx) - .to.emit(optimismUptimeFeed, 'AnswerUpdated') - .withArgs(0, 3 /** roundId */, timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(0) - expect(await optimismUptimeFeed.latestTimestamp()).to.equal(timestamp) - }) - - it(`should update status when status has changed and incoming timestamp is the same as latest`, async () => { - const timestamp = await optimismUptimeFeed.latestTimestamp() - let tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(optimismUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(1) - - // Submit another status update, different status, same timestamp should update - tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - await expect(tx) - .to.emit(optimismUptimeFeed, 'AnswerUpdated') - .withArgs(0, 3 /** roundId */, timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(0) - expect(await optimismUptimeFeed.latestTimestamp()).to.equal(timestamp) - }) - - it('should ignore out-of-order updates', async () => { - const timestamp = (await optimismUptimeFeed.latestTimestamp()).add(10_000) - // Update status - let tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(optimismUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(1) - - // Update with different status, but stale timestamp, should be ignored - const staleTimestamp = timestamp.sub(1000) - tx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(false, staleTimestamp) - await expect(tx).to.not.emit(optimismUptimeFeed, 'AnswerUpdated') - await expect(tx).to.emit(optimismUptimeFeed, 'UpdateIgnored') - }) - }) - - describe('AggregatorV3Interface', () => { - it('should return valid answer from getRoundData and latestRoundData', async () => { - let [roundId, answer, startedAt, updatedAt, answeredInRound] = - await optimismUptimeFeed.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - expect(answeredInRound).to.equal(roundId) - - // Submit status update with different status and newer timestamp, should update - const timestamp = (startedAt as BigNumber).add(1000) - await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - ;[roundId, answer, startedAt, updatedAt, answeredInRound] = - await optimismUptimeFeed.getRoundData(2) - expect(roundId).to.equal(2) - expect(answer).to.equal(1) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(timestamp) - expect(updatedAt).to.equal(updatedAt) - - // Check that last round is still returning the correct data - ;[roundId, answer, startedAt, updatedAt, answeredInRound] = - await optimismUptimeFeed.getRoundData(1) - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(startedAt) - expect(updatedAt).to.equal(updatedAt) - - // Assert latestRoundData corresponds to latest round id - expect(await optimismUptimeFeed.getRoundData(2)).to.deep.equal( - await optimismUptimeFeed.latestRoundData(), - ) - }) - - it('should revert from #getRoundData when round does not yet exist (future roundId)', async () => { - expect(optimismUptimeFeed.getRoundData(2)).to.be.revertedWith( - 'NoDataPresent()', - ) - }) - - it('should revert from #getAnswer when round does not yet exist (future roundId)', async () => { - expect(optimismUptimeFeed.getAnswer(2)).to.be.revertedWith( - 'NoDataPresent()', - ) - }) - - it('should revert from #getTimestamp when round does not yet exist (future roundId)', async () => { - expect(optimismUptimeFeed.getTimestamp(2)).to.be.revertedWith( - 'NoDataPresent()', - ) - }) - }) - - describe('Protect reads on AggregatorV2V3Interface functions', () => { - it('should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted', async () => { - // Sanity - consumer is not whitelisted - expect(await optimismUptimeFeed.checkEnabled()).to.be.true - expect( - await optimismUptimeFeed.hasAccess(uptimeFeedConsumer.address, '0x00'), - ).to.be.false - - // Assert reads are not possible from consuming contract - await expect(uptimeFeedConsumer.latestAnswer()).to.be.revertedWith( - 'No access', - ) - await expect(uptimeFeedConsumer.latestRoundData()).to.be.revertedWith( - 'No access', - ) - }) - - it('should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted', async () => { - // Whitelist consumer - await optimismUptimeFeed.addAccess(uptimeFeedConsumer.address) - // Sanity - consumer is whitelisted - expect(await optimismUptimeFeed.checkEnabled()).to.be.true - expect( - await optimismUptimeFeed.hasAccess(uptimeFeedConsumer.address, '0x00'), - ).to.be.true - - // Assert reads are possible from consuming contract - expect(await uptimeFeedConsumer.latestAnswer()).to.be.equal('0') - const [roundId, answer] = await uptimeFeedConsumer.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - }) - }) - - describe('Gas costs', () => { - it('should consume a known amount of gas for updates @skip-coverage', async () => { - // Sanity - start at flag = 0 (`false`) - expect(await optimismUptimeFeed.latestAnswer()).to.equal(0) - let timestamp = await optimismUptimeFeed.latestTimestamp() - - // Gas for no update - timestamp = timestamp.add(1000) - const _noUpdateTx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - const noUpdateTx = await _noUpdateTx.wait(1) - // Assert no update - expect(await optimismUptimeFeed.latestAnswer()).to.equal(0) - expect(noUpdateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 38594, - gasUsedDeviation, - ) - - // Gas for update - timestamp = timestamp.add(1000) - const _updateTx = await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - const updateTx = await _updateTx.wait(1) - // Assert update - expect(await optimismUptimeFeed.latestAnswer()).to.equal(1) - expect(updateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 60170, - gasUsedDeviation, - ) - }) - - describe('Aggregator interface', () => { - beforeEach(async () => { - const timestamp = (await optimismUptimeFeed.latestTimestamp()).add(1000) - // Initialise a round - await optimismUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - }) - - it('should consume a known amount of gas for getRoundData(uint80) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.getRoundData(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30952, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestRoundData() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestRoundData(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28523, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestAnswer() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestAnswer(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28329, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestTimestamp() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestTimestamp(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28229, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestRound() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestRound(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28245, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for getAnswer(roundId) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.getAnswer(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30682, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for getTimestamp(roundId) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await optimismUptimeFeed - .connect(l2Messenger) - .populateTransaction.getTimestamp(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30570, - gasUsedDeviation, - ) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/OptimismValidator.test.ts b/contracts/test/v0.8/L2EP/OptimismValidator.test.ts deleted file mode 100644 index ee69211f56..0000000000 --- a/contracts/test/v0.8/L2EP/OptimismValidator.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber, Contract, ContractFactory } from 'ethers' -import { expect } from 'chai' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -/// Pick ABIs from compilation -// @ts-ignore -import { abi as optimismSequencerStatusRecorderAbi } from '../../../artifacts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol/OptimismSequencerUptimeFeed.json' -// @ts-ignore -import { abi as optimismL1CrossDomainMessengerAbi } from '@eth-optimism/contracts/artifacts/contracts/L1/messaging/L1CrossDomainMessenger.sol' -// @ts-ignore -import { abi as aggregatorAbi } from '../../../artifacts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol/AggregatorV2V3Interface.json' - -describe('OptimismValidator', () => { - const GAS_LIMIT = BigNumber.from(1_900_000) - /** Fake L2 target */ - const L2_SEQ_STATUS_RECORDER_ADDRESS = - '0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b' - let optimismValidator: Contract - let optimismUptimeFeedFactory: ContractFactory - let mockOptimismL1CrossDomainMessenger: Contract - let deployer: SignerWithAddress - let eoaValidator: SignerWithAddress - - before(async () => { - const accounts = await ethers.getSigners() - deployer = accounts[0] - eoaValidator = accounts[1] - }) - - beforeEach(async () => { - // Required for building the calldata - optimismUptimeFeedFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol:OptimismSequencerUptimeFeed', - deployer, - ) - - // Optimism Messenger contract on L1 - const mockOptimismL1CrossDomainMessengerFactory = - await ethers.getContractFactory( - 'src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol:MockOptimismL1CrossDomainMessenger', - ) - mockOptimismL1CrossDomainMessenger = - await mockOptimismL1CrossDomainMessengerFactory.deploy() - - // Contract under test - const optimismValidatorFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/optimism/OptimismValidator.sol:OptimismValidator', - deployer, - ) - - optimismValidator = await optimismValidatorFactory.deploy( - mockOptimismL1CrossDomainMessenger.address, - L2_SEQ_STATUS_RECORDER_ADDRESS, - GAS_LIMIT, - ) - }) - - describe('#setGasLimit', () => { - it('correctly updates the gas limit', async () => { - const newGasLimit = BigNumber.from(2_000_000) - const tx = await optimismValidator.setGasLimit(newGasLimit) - await tx.wait() - const currentGasLimit = await optimismValidator.getGasLimit() - expect(currentGasLimit).to.equal(newGasLimit) - }) - }) - - describe('#validate', () => { - it('reverts if called by account with no access', async () => { - await expect( - optimismValidator.connect(eoaValidator).validate(0, 0, 1, 1), - ).to.be.revertedWith('No access') - }) - - it('posts sequencer status when there is not status change', async () => { - await optimismValidator.addAccess(eoaValidator.address) - - const currentBlock = await ethers.provider.getBlock('latest') - const futureTimestamp = currentBlock.timestamp + 5000 - - await ethers.provider.send('evm_setNextBlockTimestamp', [futureTimestamp]) - const sequencerStatusRecorderCallData = - optimismUptimeFeedFactory.interface.encodeFunctionData('updateStatus', [ - false, - futureTimestamp, - ]) - - await expect(optimismValidator.connect(eoaValidator).validate(0, 0, 0, 0)) - .to.emit(mockOptimismL1CrossDomainMessenger, 'SentMessage') - .withArgs( - L2_SEQ_STATUS_RECORDER_ADDRESS, - optimismValidator.address, - sequencerStatusRecorderCallData, - 0, - GAS_LIMIT, - ) - }) - - it('post sequencer offline', async () => { - await optimismValidator.addAccess(eoaValidator.address) - - const currentBlock = await ethers.provider.getBlock('latest') - const futureTimestamp = currentBlock.timestamp + 10000 - - await ethers.provider.send('evm_setNextBlockTimestamp', [futureTimestamp]) - const sequencerStatusRecorderCallData = - optimismUptimeFeedFactory.interface.encodeFunctionData('updateStatus', [ - true, - futureTimestamp, - ]) - - await expect(optimismValidator.connect(eoaValidator).validate(0, 0, 1, 1)) - .to.emit(mockOptimismL1CrossDomainMessenger, 'SentMessage') - .withArgs( - L2_SEQ_STATUS_RECORDER_ADDRESS, - optimismValidator.address, - sequencerStatusRecorderCallData, - 0, - GAS_LIMIT, - ) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/ScrollCrossDomainForwarder.test.ts b/contracts/test/v0.8/L2EP/ScrollCrossDomainForwarder.test.ts deleted file mode 100644 index 923d41326a..0000000000 --- a/contracts/test/v0.8/L2EP/ScrollCrossDomainForwarder.test.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { publicAbi } from '../../test-helpers/helpers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let newL1OwnerAddress: string -let forwarderFactory: ContractFactory -let greeterFactory: ContractFactory -let crossDomainMessengerFactory: ContractFactory -let crossDomainMessenger: Contract -let forwarder: Contract -let greeter: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - - // forwarder config - l1OwnerAddress = owner.address - newL1OwnerAddress = stranger.address - - // Contract factories - forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol:ScrollCrossDomainForwarder', - owner, - ) - greeterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Greeter.sol:Greeter', - owner, - ) - crossDomainMessengerFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MockScrollCrossDomainMessenger.sol:MockScrollCrossDomainMessenger', - ) -}) - -describe('ScrollCrossDomainForwarder', () => { - beforeEach(async () => { - crossDomainMessenger = - await crossDomainMessengerFactory.deploy(l1OwnerAddress) - forwarder = await forwarderFactory.deploy( - crossDomainMessenger.address, - l1OwnerAddress, - ) - greeter = await greeterFactory.deploy(forwarder.address) - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(forwarder, [ - 'typeAndVersion', - 'crossDomainMessenger', - 'forward', - 'l1Owner', - 'transferL1Ownership', - 'acceptL1Ownership', - // ConfirmedOwner methods: - 'owner', - 'transferOwnership', - 'acceptOwnership', - ]) - }) - - describe('#constructor', () => { - it('should set the owner correctly', async () => { - const response = await forwarder.owner() - assert.equal(response, owner.address) - }) - - it('should set the l1Owner correctly', async () => { - const response = await forwarder.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - - it('should set the crossdomain messenger correctly', async () => { - const response = await forwarder.crossDomainMessenger() - assert.equal(response, crossDomainMessenger.address) - }) - - it('should set the typeAndVersion correctly', async () => { - const response = await forwarder.typeAndVersion() - assert.equal(response, 'ScrollCrossDomainForwarder 1.0.0') - }) - }) - - describe('#forward', () => { - it('should not be callable by unknown address', async () => { - await expect( - forwarder.connect(stranger).forward(greeter.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should revert when contract call reverts', async () => { - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [''], - ) - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ).to.be.revertedWith('Invalid greeting length') - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - forwarder.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should not be callable by L2 owner', async () => { - const forwarderOwner = await forwarder.owner() - assert.equal(forwarderOwner, owner.address) - - await expect( - forwarder.connect(owner).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await forwarder.l1Owner() - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ) - .to.emit(forwarder, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, newL1OwnerAddress) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await forwarder.l1Owner() - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [ethers.constants.AddressZero], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ) - .to.emit(forwarder, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - const forwardData = forwarderFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ).to.be.revertedWith('Must be proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await forwarder.l1Owner() - - // Transfer ownership - const forwardTransferData = forwarderFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - await crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardTransferData, // message - 0, // gasLimit - ) - - const forwardAcceptData = forwarderFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - // Simulate cross-chain message from another sender - await crossDomainMessenger._setMockMessageSender(newL1OwnerAddress) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - forwarder.address, // target - 0, // value - forwardAcceptData, // message - 0, // gasLimit - ), - ) - .to.emit(forwarder, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, newL1OwnerAddress) - - const updatedL1Owner = await forwarder.l1Owner() - assert.equal(updatedL1Owner, newL1OwnerAddress) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/ScrollCrossDomainGovernor.test.ts b/contracts/test/v0.8/L2EP/ScrollCrossDomainGovernor.test.ts deleted file mode 100644 index d2211145bb..0000000000 --- a/contracts/test/v0.8/L2EP/ScrollCrossDomainGovernor.test.ts +++ /dev/null @@ -1,459 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import etherslib, { Contract, ContractFactory } from 'ethers' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { publicAbi, stripHexPrefix } from '../../test-helpers/helpers' - -let owner: SignerWithAddress -let stranger: SignerWithAddress -let l1OwnerAddress: string -let newL1OwnerAddress: string -let governorFactory: ContractFactory -let greeterFactory: ContractFactory -let multisendFactory: ContractFactory -let crossDomainMessengerFactory: ContractFactory -let crossDomainMessenger: Contract -let governor: Contract -let greeter: Contract -let multisend: Contract - -before(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - - // governor config - l1OwnerAddress = owner.address - newL1OwnerAddress = stranger.address - - // Contract factories - governorFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol:ScrollCrossDomainGovernor', - owner, - ) - greeterFactory = await ethers.getContractFactory( - 'src/v0.8/tests/Greeter.sol:Greeter', - owner, - ) - multisendFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MultiSend.sol:MultiSend', - owner, - ) - crossDomainMessengerFactory = await ethers.getContractFactory( - 'src/v0.8/vendor/MockScrollCrossDomainMessenger.sol:MockScrollCrossDomainMessenger', - ) -}) - -describe('ScrollCrossDomainGovernor', () => { - beforeEach(async () => { - crossDomainMessenger = - await crossDomainMessengerFactory.deploy(l1OwnerAddress) - governor = await governorFactory.deploy( - crossDomainMessenger.address, - l1OwnerAddress, - ) - greeter = await greeterFactory.deploy(governor.address) - multisend = await multisendFactory.deploy() - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(governor, [ - 'typeAndVersion', - 'crossDomainMessenger', - 'forward', - 'forwardDelegate', - 'l1Owner', - 'transferL1Ownership', - 'acceptL1Ownership', - // ConfirmedOwner methods: - 'owner', - 'transferOwnership', - 'acceptOwnership', - ]) - }) - - describe('#constructor', () => { - it('should set the owner correctly', async () => { - const response = await governor.owner() - assert.equal(response, owner.address) - }) - - it('should set the l1Owner correctly', async () => { - const response = await governor.l1Owner() - assert.equal(response, l1OwnerAddress) - }) - - it('should set the crossdomain messenger correctly', async () => { - const response = await governor.crossDomainMessenger() - assert.equal(response, crossDomainMessenger.address) - }) - - it('should set the typeAndVersion correctly', async () => { - const response = await governor.typeAndVersion() - assert.equal(response, 'ScrollCrossDomainGovernor 1.0.0') - }) - }) - - describe('#forward', () => { - it('should not be callable by unknown address', async () => { - await expect( - governor.connect(stranger).forward(greeter.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger or owner') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should be callable by L2 owner', async () => { - const newGreeting = 'hello' - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [newGreeting], - ) - await governor.connect(owner).forward(greeter.address, setGreetingData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, newGreeting) - }) - - it('should revert when contract call reverts', async () => { - const setGreetingData = greeterFactory.interface.encodeFunctionData( - 'setGreeting', - [''], - ) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forward', - [greeter.address, setGreetingData], - ) - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ).to.be.revertedWith('Invalid greeting length') - }) - }) - - describe('#forwardDelegate', () => { - it('should not be callable by unknown address', async () => { - await expect( - governor.connect(stranger).forwardDelegate(multisend.address, '0x'), - ).to.be.revertedWith('Sender is not the L2 messenger or owner') - }) - - it('should be callable by crossdomain messenger address / L1 owner', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'bar', - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forwardDelegate', - [multisend.address, multisendData], - ) - - await crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, 'bar') - }) - - it('should be callable by L2 owner', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'bar', - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - await governor - .connect(owner) - .forwardDelegate(multisend.address, multisendData) - - const updatedGreeting = await greeter.greeting() - assert.equal(updatedGreeting, 'bar') - }) - - it('should revert batch when one call fails', async () => { - const calls = [ - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - 'foo', - ]), - value: 0, - }, - { - to: greeter.address, - data: greeterFactory.interface.encodeFunctionData('setGreeting', [ - '', // should revert - ]), - value: 0, - }, - ] - const multisendData = encodeMultisendData(multisend.interface, calls) - const forwardData = governorFactory.interface.encodeFunctionData( - 'forwardDelegate', - [multisend.address, multisendData], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ).to.be.revertedWith('Governor delegatecall reverted') - - const greeting = await greeter.greeting() - assert.equal(greeting, '') // Unchanged - }) - - it('should bubble up revert when contract call reverts', async () => { - const triggerRevertData = - greeterFactory.interface.encodeFunctionData('triggerRevert') - const forwardData = governorFactory.interface.encodeFunctionData( - 'forwardDelegate', - [greeter.address, triggerRevertData], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ).to.be.revertedWith('Greeter: revert triggered') - }) - }) - - describe('#transferL1Ownership', () => { - it('should not be callable by non-owners', async () => { - await expect( - governor.connect(stranger).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should not be callable by L2 owner', async () => { - const governorOwner = await governor.owner() - assert.equal(governorOwner, owner.address) - - await expect( - governor.connect(owner).transferL1Ownership(stranger.address), - ).to.be.revertedWith('Sender is not the L2 messenger') - }) - - it('should be callable by current L1 owner', async () => { - const currentL1Owner = await governor.l1Owner() - const forwardData = governorFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ) - .to.emit(governor, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, newL1OwnerAddress) - }) - - it('should be callable by current L1 owner to zero address', async () => { - const currentL1Owner = await governor.l1Owner() - const forwardData = governorFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [ethers.constants.AddressZero], - ) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ) - .to.emit(governor, 'L1OwnershipTransferRequested') - .withArgs(currentL1Owner, ethers.constants.AddressZero) - }) - }) - - describe('#acceptL1Ownership', () => { - it('should not be callable by non pending-owners', async () => { - const forwardData = governorFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardData, // message - 0, // gasLimit - ), - ).to.be.revertedWith('Must be proposed L1 owner') - }) - - it('should be callable by pending L1 owner', async () => { - const currentL1Owner = await governor.l1Owner() - - // Transfer ownership - const forwardTransferData = governorFactory.interface.encodeFunctionData( - 'transferL1Ownership', - [newL1OwnerAddress], - ) - await crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardTransferData, // message - 0, // gasLimit - ) - - const forwardAcceptData = governorFactory.interface.encodeFunctionData( - 'acceptL1Ownership', - [], - ) - // Simulate cross-chain message from another sender - await crossDomainMessenger._setMockMessageSender(newL1OwnerAddress) - - await expect( - crossDomainMessenger // Simulate cross-chain message - .connect(stranger) - ['sendMessage(address,uint256,bytes,uint256)']( - governor.address, // target - 0, // value - forwardAcceptData, // message - 0, // gasLimit - ), - ) - .to.emit(governor, 'L1OwnershipTransferred') - .withArgs(currentL1Owner, newL1OwnerAddress) - - const updatedL1Owner = await governor.l1Owner() - assert.equal(updatedL1Owner, newL1OwnerAddress) - }) - }) -}) - -// Multisend contract helpers - -/** - * Encodes an underlying transaction for the Multisend contract - * - * @param operation 0 for CALL, 1 for DELEGATECALL - * @param to tx target address - * @param value tx value - * @param data tx data - */ -export function encodeTxData( - operation: number, - to: string, - value: number, - data: string, -): string { - const dataBuffer = Buffer.from(stripHexPrefix(data), 'hex') - const types = ['uint8', 'address', 'uint256', 'uint256', 'bytes'] - const values = [operation, to, value, dataBuffer.length, dataBuffer] - const encoded = ethers.utils.solidityPack(types, values) - return stripHexPrefix(encoded) -} - -/** - * Encodes a Multisend call - * - * @param MultisendInterface Ethers Interface object of the Multisend contract - * @param transactions one or more transactions to include in the Multisend call - * @param to tx target address - * @param value tx value - * @param data tx data - */ -export function encodeMultisendData( - MultisendInterface: etherslib.utils.Interface, - transactions: { to: string; value: number; data: string }[], -): string { - let nestedTransactionData = '0x' - for (const transaction of transactions) { - nestedTransactionData += encodeTxData( - 0, - transaction.to, - transaction.value, - transaction.data, - ) - } - const encodedMultisendFnData = MultisendInterface.encodeFunctionData( - 'multiSend', - [nestedTransactionData], - ) - return encodedMultisendFnData -} diff --git a/contracts/test/v0.8/L2EP/ScrollSequencerUptimeFeed.test.ts b/contracts/test/v0.8/L2EP/ScrollSequencerUptimeFeed.test.ts deleted file mode 100644 index d0fecf3b18..0000000000 --- a/contracts/test/v0.8/L2EP/ScrollSequencerUptimeFeed.test.ts +++ /dev/null @@ -1,424 +0,0 @@ -import { ethers, network } from 'hardhat' -import { BigNumber, Contract } from 'ethers' -import { expect } from 'chai' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' - -describe('ScrollSequencerUptimeFeed', () => { - let l2CrossDomainMessenger: Contract - let scrollUptimeFeed: Contract - let uptimeFeedConsumer: Contract - let deployer: SignerWithAddress - let l1Owner: SignerWithAddress - let l2Messenger: SignerWithAddress - let dummy: SignerWithAddress - const gasUsedDeviation = 100 - const initialStatus = 0 - - before(async () => { - const accounts = await ethers.getSigners() - deployer = accounts[0] - l1Owner = accounts[1] - dummy = accounts[3] - - const l2CrossDomainMessengerFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol:MockScrollL2CrossDomainMessenger', - deployer, - ) - - l2CrossDomainMessenger = await l2CrossDomainMessengerFactory.deploy() - - // Pretend we're on L2 - await network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [l2CrossDomainMessenger.address], - }) - l2Messenger = await ethers.getSigner(l2CrossDomainMessenger.address) - // Credit the L2 messenger with some ETH - await dummy.sendTransaction({ - to: l2Messenger.address, - value: ethers.utils.parseEther('10'), - }) - }) - - beforeEach(async () => { - const scrollSequencerStatusRecorderFactory = - await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol:ScrollSequencerUptimeFeed', - deployer, - ) - scrollUptimeFeed = await scrollSequencerStatusRecorderFactory.deploy( - l1Owner.address, - l2CrossDomainMessenger.address, - initialStatus, - ) - - // Set mock sender in mock L2 messenger contract - await l2CrossDomainMessenger.setSender(l1Owner.address) - - // Mock consumer - const statusFeedConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/tests/FeedConsumer.sol:FeedConsumer', - deployer, - ) - uptimeFeedConsumer = await statusFeedConsumerFactory.deploy( - scrollUptimeFeed.address, - ) - }) - - describe('constructor', () => { - it('should have been deployed with the correct initial state', async () => { - const l1Sender = await scrollUptimeFeed.l1Sender() - expect(l1Sender).to.equal(l1Owner.address) - const { roundId, answer } = await scrollUptimeFeed.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(initialStatus) - }) - }) - - describe('#updateStatus', () => { - it('should revert if called by an address that is not the L2 Cross Domain Messenger', async () => { - const timestamp = await scrollUptimeFeed.latestTimestamp() - expect( - scrollUptimeFeed.connect(dummy).updateStatus(true, timestamp), - ).to.be.revertedWith('InvalidSender') - }) - - it('should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender', async () => { - const timestamp = await scrollUptimeFeed.latestTimestamp() - await l2CrossDomainMessenger.setSender(dummy.address) - expect( - scrollUptimeFeed.connect(dummy).updateStatus(true, timestamp), - ).to.be.revertedWith('InvalidSender') - }) - - it(`should update status when status has not changed and incoming timestamp is the same as latest`, async () => { - const timestamp = await scrollUptimeFeed.latestTimestamp() - let tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(scrollUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) - - const latestRoundBeforeUpdate = await scrollUptimeFeed.latestRoundData() - - tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp.add(200)) - - // Submit another status update with the same status - const latestBlock = await ethers.provider.getBlock('latest') - - await expect(tx) - .to.emit(scrollUptimeFeed, 'RoundUpdated') - .withArgs(1, latestBlock.timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) - expect(await scrollUptimeFeed.latestTimestamp()).to.equal(timestamp) - - // Verify that latest round has been properly updated - const latestRoundDataAfterUpdate = - await scrollUptimeFeed.latestRoundData() - expect(latestRoundDataAfterUpdate.roundId).to.equal( - latestRoundBeforeUpdate.roundId, - ) - expect(latestRoundDataAfterUpdate.answer).to.equal( - latestRoundBeforeUpdate.answer, - ) - expect(latestRoundDataAfterUpdate.startedAt).to.equal( - latestRoundBeforeUpdate.startedAt, - ) - expect(latestRoundDataAfterUpdate.answeredInRound).to.equal( - latestRoundBeforeUpdate.answeredInRound, - ) - expect(latestRoundDataAfterUpdate.updatedAt).to.equal( - latestBlock.timestamp, - ) - }) - - it(`should update status when status has changed and incoming timestamp is newer than the latest`, async () => { - let timestamp = await scrollUptimeFeed.latestTimestamp() - let tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(scrollUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp.add(2000) - tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - await expect(tx) - .to.emit(scrollUptimeFeed, 'AnswerUpdated') - .withArgs(0, 3 /** roundId */, timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) - expect(await scrollUptimeFeed.latestTimestamp()).to.equal(timestamp) - }) - - it(`should update status when status has changed and incoming timestamp is the same as latest`, async () => { - const timestamp = await scrollUptimeFeed.latestTimestamp() - let tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(scrollUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) - - // Submit another status update, different status, same timestamp should update - tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - await expect(tx) - .to.emit(scrollUptimeFeed, 'AnswerUpdated') - .withArgs(0, 3 /** roundId */, timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) - expect(await scrollUptimeFeed.latestTimestamp()).to.equal(timestamp) - }) - - it('should ignore out-of-order updates', async () => { - const timestamp = (await scrollUptimeFeed.latestTimestamp()).add(10_000) - // Update status - let tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - await expect(tx) - .to.emit(scrollUptimeFeed, 'AnswerUpdated') - .withArgs(1, 2 /** roundId */, timestamp) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) - - // Update with different status, but stale timestamp, should be ignored - const staleTimestamp = timestamp.sub(1000) - tx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(false, staleTimestamp) - await expect(tx).to.not.emit(scrollUptimeFeed, 'AnswerUpdated') - await expect(tx).to.emit(scrollUptimeFeed, 'UpdateIgnored') - }) - }) - - describe('AggregatorV3Interface', () => { - it('should return valid answer from getRoundData and latestRoundData', async () => { - let [roundId, answer, startedAt, updatedAt, answeredInRound] = - await scrollUptimeFeed.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(updatedAt) - - // Submit status update with different status and newer timestamp, should update - const timestamp = (startedAt as BigNumber).add(1000) - await scrollUptimeFeed.connect(l2Messenger).updateStatus(true, timestamp) - ;[roundId, answer, startedAt, updatedAt, answeredInRound] = - await scrollUptimeFeed.getRoundData(2) - expect(roundId).to.equal(2) - expect(answer).to.equal(1) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(timestamp) - expect(updatedAt.lte(startedAt)).to.be.true - - // Check that last round is still returning the correct data - ;[roundId, answer, startedAt, updatedAt, answeredInRound] = - await scrollUptimeFeed.getRoundData(1) - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - expect(answeredInRound).to.equal(roundId) - expect(startedAt).to.equal(updatedAt) - - // Assert latestRoundData corresponds to latest round id - expect(await scrollUptimeFeed.getRoundData(2)).to.deep.equal( - await scrollUptimeFeed.latestRoundData(), - ) - }) - - it('should revert from #getRoundData when round does not yet exist (future roundId)', async () => { - expect(scrollUptimeFeed.getRoundData(2)).to.be.revertedWith( - 'NoDataPresent()', - ) - }) - - it('should revert from #getAnswer when round does not yet exist (future roundId)', async () => { - expect(scrollUptimeFeed.getAnswer(2)).to.be.revertedWith( - 'NoDataPresent()', - ) - }) - - it('should revert from #getTimestamp when round does not yet exist (future roundId)', async () => { - expect(scrollUptimeFeed.getTimestamp(2)).to.be.revertedWith( - 'NoDataPresent()', - ) - }) - }) - - describe('Protect reads on AggregatorV2V3Interface functions', () => { - it('should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted', async () => { - // Sanity - consumer is not whitelisted - expect(await scrollUptimeFeed.checkEnabled()).to.be.true - expect( - await scrollUptimeFeed.hasAccess(uptimeFeedConsumer.address, '0x00'), - ).to.be.false - - // Assert reads are not possible from consuming contract - await expect(uptimeFeedConsumer.latestAnswer()).to.be.revertedWith( - 'No access', - ) - await expect(uptimeFeedConsumer.latestRoundData()).to.be.revertedWith( - 'No access', - ) - }) - - it('should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted', async () => { - // Whitelist consumer - await scrollUptimeFeed.addAccess(uptimeFeedConsumer.address) - // Sanity - consumer is whitelisted - expect(await scrollUptimeFeed.checkEnabled()).to.be.true - expect( - await scrollUptimeFeed.hasAccess(uptimeFeedConsumer.address, '0x00'), - ).to.be.true - - // Assert reads are possible from consuming contract - expect(await uptimeFeedConsumer.latestAnswer()).to.be.equal('0') - const [roundId, answer] = await uptimeFeedConsumer.latestRoundData() - expect(roundId).to.equal(1) - expect(answer).to.equal(0) - }) - }) - - describe('Gas costs', () => { - it('should consume a known amount of gas for updates @skip-coverage', async () => { - // Sanity - start at flag = 0 (`false`) - expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) - let timestamp = await scrollUptimeFeed.latestTimestamp() - - // Gas for no update - timestamp = timestamp.add(1000) - const _noUpdateTx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(false, timestamp) - const noUpdateTx = await _noUpdateTx.wait(1) - // Assert no update - expect(await scrollUptimeFeed.latestAnswer()).to.equal(0) - expect(noUpdateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 38594, - gasUsedDeviation, - ) - - // Gas for update - timestamp = timestamp.add(1000) - const _updateTx = await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - const updateTx = await _updateTx.wait(1) - // Assert update - expect(await scrollUptimeFeed.latestAnswer()).to.equal(1) - expect(updateTx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 58458, - gasUsedDeviation, - ) - }) - - describe('Aggregator interface', () => { - beforeEach(async () => { - const timestamp = (await scrollUptimeFeed.latestTimestamp()).add(1000) - // Initialise a round - await scrollUptimeFeed - .connect(l2Messenger) - .updateStatus(true, timestamp) - }) - - it('should consume a known amount of gas for getRoundData(uint80) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.getRoundData(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30952, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestRoundData() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestRoundData(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28523, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestAnswer() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestAnswer(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28229, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestTimestamp() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestTimestamp(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28129, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for latestRound() @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.latestRound(), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 28145, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for getAnswer(roundId) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.getAnswer(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30682, - gasUsedDeviation, - ) - }) - - it('should consume a known amount of gas for getTimestamp(roundId) @skip-coverage', async () => { - const _tx = await l2Messenger.sendTransaction( - await scrollUptimeFeed - .connect(l2Messenger) - .populateTransaction.getTimestamp(1), - ) - const tx = await _tx.wait(1) - expect(tx.cumulativeGasUsed.toNumber()).to.be.closeTo( - 30570, - gasUsedDeviation, - ) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/L2EP/ScrollValidator.test.ts b/contracts/test/v0.8/L2EP/ScrollValidator.test.ts deleted file mode 100644 index 94205a0311..0000000000 --- a/contracts/test/v0.8/L2EP/ScrollValidator.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber, Contract, ContractFactory } from 'ethers' -import { expect } from 'chai' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' - -describe('ScrollValidator', () => { - const GAS_LIMIT = BigNumber.from(1_900_000) - /** Fake L2 target */ - const L2_SEQ_STATUS_RECORDER_ADDRESS = - '0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b' - let scrollValidator: Contract - let l1MessageQueue: Contract - let scrollUptimeFeedFactory: ContractFactory - let mockScrollL1CrossDomainMessenger: Contract - let deployer: SignerWithAddress - let eoaValidator: SignerWithAddress - - before(async () => { - const accounts = await ethers.getSigners() - deployer = accounts[0] - eoaValidator = accounts[1] - }) - - beforeEach(async () => { - // Required for building the calldata - scrollUptimeFeedFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol:ScrollSequencerUptimeFeed', - deployer, - ) - - // Scroll Messenger contract on L1 - const mockScrollL1CrossDomainMessengerFactory = - await ethers.getContractFactory( - 'src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol:MockScrollL1CrossDomainMessenger', - ) - mockScrollL1CrossDomainMessenger = - await mockScrollL1CrossDomainMessengerFactory.deploy() - - // Scroll Message Queue contract on L1 - const l1MessageQueueFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol:MockScrollL1MessageQueue', - deployer, - ) - l1MessageQueue = await l1MessageQueueFactory.deploy() - - // Contract under test - const scrollValidatorFactory = await ethers.getContractFactory( - 'src/v0.8/l2ep/dev/scroll/ScrollValidator.sol:ScrollValidator', - deployer, - ) - - scrollValidator = await scrollValidatorFactory.deploy( - mockScrollL1CrossDomainMessenger.address, - L2_SEQ_STATUS_RECORDER_ADDRESS, - l1MessageQueue.address, - GAS_LIMIT, - ) - }) - - describe('#setGasLimit', () => { - it('correctly updates the gas limit', async () => { - const newGasLimit = BigNumber.from(2_000_000) - const tx = await scrollValidator.setGasLimit(newGasLimit) - await tx.wait() - const currentGasLimit = await scrollValidator.getGasLimit() - expect(currentGasLimit).to.equal(newGasLimit) - }) - }) - - describe('#validate', () => { - it('reverts if called by account with no access', async () => { - await expect( - scrollValidator.connect(eoaValidator).validate(0, 0, 1, 1), - ).to.be.revertedWith('No access') - }) - - it('posts sequencer status when there is not status change', async () => { - await scrollValidator.addAccess(eoaValidator.address) - - const currentBlock = await ethers.provider.getBlock('latest') - const futureTimestamp = currentBlock.timestamp + 5000 - - await ethers.provider.send('evm_setNextBlockTimestamp', [futureTimestamp]) - const sequencerStatusRecorderCallData = - scrollUptimeFeedFactory.interface.encodeFunctionData('updateStatus', [ - false, - futureTimestamp, - ]) - - await expect(scrollValidator.connect(eoaValidator).validate(0, 0, 0, 0)) - .to.emit(mockScrollL1CrossDomainMessenger, 'SentMessage') - .withArgs( - scrollValidator.address, // sender - L2_SEQ_STATUS_RECORDER_ADDRESS, // target - 0, // value - 0, // nonce - GAS_LIMIT, // gas limit - sequencerStatusRecorderCallData, // message - ) - }) - - it('post sequencer offline', async () => { - await scrollValidator.addAccess(eoaValidator.address) - - const currentBlock = await ethers.provider.getBlock('latest') - const futureTimestamp = currentBlock.timestamp + 10000 - - await ethers.provider.send('evm_setNextBlockTimestamp', [futureTimestamp]) - const sequencerStatusRecorderCallData = - scrollUptimeFeedFactory.interface.encodeFunctionData('updateStatus', [ - true, - futureTimestamp, - ]) - - await expect(scrollValidator.connect(eoaValidator).validate(0, 0, 1, 1)) - .to.emit(mockScrollL1CrossDomainMessenger, 'SentMessage') - .withArgs( - scrollValidator.address, // sender - L2_SEQ_STATUS_RECORDER_ADDRESS, // target - 0, // value - 0, // nonce - GAS_LIMIT, // gas limit - sequencerStatusRecorderCallData, // message - ) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts index 0a46b4805e..8bc4f69567 100644 --- a/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts +++ b/contracts/test/v0.8/automation/IAutomationRegistryMaster2_3.test.ts @@ -36,7 +36,7 @@ describe('IAutomationRegistryMaster2_3', () => { const checksum = ethers.utils.id(compositeABIs.join('')) const knownChecksum = fs .readFileSync( - 'src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol', + 'src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol', ) .toString() .slice(17, 83) // checksum located at top of file diff --git a/contracts/test/v0.8/vrf/BatchBlockhashStore.test.ts b/contracts/test/v0.8/vrf/BatchBlockhashStore.test.ts deleted file mode 100644 index ebdc17037c..0000000000 --- a/contracts/test/v0.8/vrf/BatchBlockhashStore.test.ts +++ /dev/null @@ -1,324 +0,0 @@ -import { assert, expect } from 'chai' -import { Contract, Signer } from 'ethers' -import { ethers } from 'hardhat' -import * as rlp from 'rlp' - -function range(size: number, startAt = 0) { - return [...Array(size).keys()].map((i) => i + startAt) -} - -describe('BatchBlockhashStore', () => { - let blockhashStore: Contract - let batchBHS: Contract - let owner: Signer - - beforeEach(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - - const bhFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/dev/BlockhashStore.sol:BlockhashStore', - accounts[0], - ) - - blockhashStore = await bhFactory.deploy() - - const batchBHSFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/BatchBlockhashStore.sol:BatchBlockhashStore', - accounts[0], - ) - - batchBHS = await batchBHSFactory.deploy(blockhashStore.address) - - // Mine some blocks so that we have some blockhashes to store. - for (let i = 0; i < 10; i++) { - await ethers.provider.send('evm_mine', []) - } - }) - - describe('#store', () => { - it('stores batches of blocknumbers', async () => { - const latestBlock = await ethers.provider.send('eth_blockNumber', []) - const bottomBlock = latestBlock - 5 - const numBlocks = 3 - await batchBHS.connect(owner).store(range(numBlocks, bottomBlock)) - - // Mine some blocks to confirm the store batch tx above. - for (let i = 0; i < 2; i++) { - await ethers.provider.send('evm_mine', []) - } - - // check the bhs if it was stored - for (let i = bottomBlock; i < bottomBlock + numBlocks; i++) { - const actualBh = await blockhashStore.connect(owner).getBlockhash(i) - const expectedBh = (await ethers.provider.getBlock(i)).hash - expect(expectedBh).to.equal(actualBh) - } - }) - - it('skips block numbers that are too far back', async () => { - // blockhash(n) fails if n is more than 256 blocks behind the current block in which - // the instruction is executing. - for (let i = 0; i < 256; i++) { - await ethers.provider.send('evm_mine', []) - } - - const gettableBlock = - (await ethers.provider.send('eth_blockNumber', [])) - 1 - - // Store 3 block numbers that are too far back, and one that is close enough. - await batchBHS.connect(owner).store([1, 2, 3, gettableBlock]) - - await ethers.provider.send('evm_mine', []) - - // Only block "250" should be stored - const actualBh = await blockhashStore - .connect(owner) - .getBlockhash(gettableBlock) - const expectedBh = (await ethers.provider.getBlock(gettableBlock)).hash - expect(expectedBh).to.equal(actualBh) - - // others were not stored - for (let i of [1, 2, 3]) { - expect( - blockhashStore.connect(owner).getBlockhash(i), - ).to.be.revertedWith('blockhash not found in store') - } - }) - }) - - describe('#getBlockhashes', () => { - it('fetches blockhashes of a batch of block numbers', async () => { - // Store a bunch of block hashes - const latestBlock = await ethers.provider.send('eth_blockNumber', []) - const bottomBlock = latestBlock - 5 - const numBlocks = 3 - await batchBHS.connect(owner).store(range(numBlocks, bottomBlock)) - - // Mine some blocks to confirm the store batch tx above. - for (let i = 0; i < 2; i++) { - await ethers.provider.send('evm_mine', []) - } - - // fetch the blocks in a batch - const actualBlockhashes = await batchBHS - .connect(owner) - .getBlockhashes(range(numBlocks, bottomBlock)) - let expectedBlockhashes = [] - for (let i = bottomBlock; i < bottomBlock + numBlocks; i++) { - const block = await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + i.toString(16), - false, - ]) - expectedBlockhashes.push(block.hash) - } - assert.deepEqual(actualBlockhashes, expectedBlockhashes) - }) - - it('returns 0x0 for block numbers without an associated blockhash', async () => { - const latestBlock = await ethers.provider.send('eth_blockNumber', []) - const bottomBlock = latestBlock - 5 - const numBlocks = 3 - const blockhashes = await batchBHS - .connect(owner) - .getBlockhashes(range(numBlocks, bottomBlock)) - const expected = [ - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - ] - assert.deepEqual(blockhashes, expected) - }) - }) - - describe('#storeVerifyHeader', () => { - it('stores batches of blocknumbers using storeVerifyHeader [ @skip-coverage ]', async () => { - // Store a single blockhash and go backwards from there using storeVerifyHeader - const latestBlock = await ethers.provider.send('eth_blockNumber', []) - await batchBHS.connect(owner).store([latestBlock]) - await ethers.provider.send('evm_mine', []) - - const numBlocks = 3 - const startBlock = latestBlock - 1 - const blockNumbers = range( - numBlocks + 1, - startBlock - numBlocks, - ).reverse() - let blockHeaders = [] - let expectedBlockhashes = [] - for (let i of blockNumbers) { - const block = await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + (i + 1).toString(16), - false, - ]) - // eip 1559 header - switch to this if we upgrade hardhat - // and use post-london forks of ethereum. - const encodedHeader = rlp.encode([ - block.parentHash, - block.sha3Uncles, - ethers.utils.arrayify(block.miner), - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - block.difficulty == '0x0' ? '0x' : block.difficulty, - block.number, - block.gasLimit, - block.gasUsed == '0x0' ? '0x' : block.gasUsed, - block.timestamp, - block.extraData, - block.mixHash, - block.nonce, - block.baseFeePerGas, - ]) - // // pre-london block header serialization - kept for prosperity - // const encodedHeader = rlp.encode([ - // block.parentHash, - // block.sha3Uncles, - // ethers.utils.arrayify(block.miner), - // block.stateRoot, - // block.transactionsRoot, - // block.receiptsRoot, - // block.logsBloom, - // block.difficulty, - // block.number, - // block.gasLimit, - // block.gasUsed == '0x0' ? '0x' : block.gasUsed, - // block.timestamp, - // block.extraData, - // block.mixHash, - // block.nonce, - // ]) - blockHeaders.push('0x' + encodedHeader.toString('hex')) - expectedBlockhashes.push( - ( - await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + i.toString(16), - false, - ]) - ).hash, - ) - } - await batchBHS - .connect(owner) - .storeVerifyHeader(blockNumbers, blockHeaders) - - // fetch blocks that were just stored and assert correctness - const actualBlockhashes = await batchBHS - .connect(owner) - .getBlockhashes(blockNumbers) - - assert.deepEqual(actualBlockhashes, expectedBlockhashes) - }) - - describe('bad input', () => { - it('reverts on mismatched input array sizes', async () => { - // Store a single blockhash and go backwards from there using storeVerifyHeader - const latestBlock = await ethers.provider.send('eth_blockNumber', []) - await batchBHS.connect(owner).store([latestBlock]) - - await ethers.provider.send('evm_mine', []) - - const numBlocks = 3 - const startBlock = latestBlock - 1 - const blockNumbers = range( - numBlocks + 1, - startBlock - numBlocks, - ).reverse() - let blockHeaders = [] - let expectedBlockhashes = [] - for (let i of blockNumbers) { - const block = await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + (i + 1).toString(16), - false, - ]) - const encodedHeader = rlp.encode([ - block.parentHash, - block.sha3Uncles, - ethers.utils.arrayify(block.miner), - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - block.difficulty == '0x0' ? '0x' : block.difficulty, - block.number, - block.gasLimit, - block.gasUsed == '0x0' ? '0x' : block.gasUsed, - block.timestamp, - block.extraData, - block.mixHash, - block.nonce, - block.baseFeePerGas, - ]) - blockHeaders.push('0x' + encodedHeader.toString('hex')) - expectedBlockhashes.push( - ( - await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + i.toString(16), - false, - ]) - ).hash, - ) - } - // remove last element to simulate different input array sizes - blockHeaders.pop() - expect( - batchBHS.connect(owner).storeVerifyHeader(blockNumbers, blockHeaders), - ).to.be.revertedWith('input array arg lengths mismatch') - }) - - it('reverts on bad block header input', async () => { - // Store a single blockhash and go backwards from there using storeVerifyHeader - const latestBlock = await ethers.provider.send('eth_blockNumber', []) - await batchBHS.connect(owner).store([latestBlock]) - - await ethers.provider.send('evm_mine', []) - - const numBlocks = 3 - const startBlock = latestBlock - 1 - const blockNumbers = range( - numBlocks + 1, - startBlock - numBlocks, - ).reverse() - let blockHeaders = [] - let expectedBlockhashes = [] - for (let i of blockNumbers) { - const block = await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + (i + 1).toString(16), - false, - ]) - const encodedHeader = rlp.encode([ - block.parentHash, - block.sha3Uncles, - ethers.utils.arrayify(block.miner), - block.stateRoot, - block.transactionsRoot, - block.receiptsRoot, - block.logsBloom, - block.difficulty == '0x0' ? '0x' : block.difficulty, - block.number, - block.gasLimit, - block.gasUsed, // incorrect: in cases where it's 0x0 it should be 0x instead. - block.timestamp, - block.extraData, - block.mixHash, - block.nonce, - block.baseFeePerGas, - ]) - blockHeaders.push('0x' + encodedHeader.toString('hex')) - expectedBlockhashes.push( - ( - await ethers.provider.send('eth_getBlockByNumber', [ - '0x' + i.toString(16), - false, - ]) - ).hash, - ) - } - expect( - batchBHS.connect(owner).storeVerifyHeader(blockNumbers, blockHeaders), - ).to.be.revertedWith('header has unknown blockhash') - }) - }) - }) -}) diff --git a/contracts/test/v0.8/vrf/VRFCoordinatorV2.test.ts b/contracts/test/v0.8/vrf/VRFCoordinatorV2.test.ts deleted file mode 100644 index 59f3811eed..0000000000 --- a/contracts/test/v0.8/vrf/VRFCoordinatorV2.test.ts +++ /dev/null @@ -1,1173 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber, Contract, Signer } from 'ethers' -import { assert, expect } from 'chai' -import { publicAbi } from '../../test-helpers/helpers' -import { randomAddressString } from 'hardhat/internal/hardhat-network/provider/utils/random' - -describe('VRFCoordinatorV2', () => { - let vrfCoordinatorV2: Contract - let vrfCoordinatorV2TestHelper: Contract - let linkToken: Contract - let blockHashStore: Contract - let mockLinkEth: Contract - let owner: Signer - let subOwner: Signer - let subOwnerAddress: string - let consumer: Signer - let random: Signer - let randomAddress: string - let oracle: Signer - const linkEth = BigNumber.from(300000000) - type config = { - minimumRequestBlockConfirmations: number - maxGasLimit: number - stalenessSeconds: number - gasAfterPaymentCalculation: number - weiPerUnitLink: BigNumber - } - let c: config - - beforeEach(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - subOwner = accounts[1] - subOwnerAddress = await subOwner.getAddress() - consumer = accounts[2] - random = accounts[3] - randomAddress = await random.getAddress() - oracle = accounts[4] - const ltFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - accounts[0], - ) - linkToken = await ltFactory.deploy() - const bhFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/dev/BlockhashStore.sol:BlockhashStore', - accounts[0], - ) - blockHashStore = await bhFactory.deploy() - const mockAggregatorV3Factory = await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - accounts[0], - ) - mockLinkEth = await mockAggregatorV3Factory.deploy(0, linkEth) - const vrfCoordinatorV2Factory = await ethers.getContractFactory( - 'src/v0.8/vrf/VRFCoordinatorV2.sol:VRFCoordinatorV2', - accounts[0], - ) - vrfCoordinatorV2 = await vrfCoordinatorV2Factory.deploy( - linkToken.address, - blockHashStore.address, - mockLinkEth.address, - ) - const vrfCoordinatorV2TestHelperFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol:VRFCoordinatorV2TestHelper', - accounts[0], - ) - vrfCoordinatorV2TestHelper = await vrfCoordinatorV2TestHelperFactory.deploy( - mockLinkEth.address, - ) - await linkToken.transfer( - subOwnerAddress, - BigNumber.from('1000000000000000000'), - ) // 1 link - await linkToken.transfer( - randomAddress, - BigNumber.from('1000000000000000000'), - ) // 1 link - c = { - minimumRequestBlockConfirmations: 1, - maxGasLimit: 1000000, - stalenessSeconds: 86400, - gasAfterPaymentCalculation: - 21000 + 5000 + 2100 + 20000 + 2 * 2100 - 15000 + 7315, - weiPerUnitLink: BigNumber.from('10000000000000000'), - } - // Note if you try and use an object, ethers - // confuses that with an override object and will error. - // It appears that only arrays work for struct args. - const fc = [0, 0, 0, 0, 0, 0, 0, 0, 0] - await vrfCoordinatorV2 - .connect(owner) - .setConfig( - c.minimumRequestBlockConfirmations, - c.maxGasLimit, - c.stalenessSeconds, - c.gasAfterPaymentCalculation, - c.weiPerUnitLink, - fc, - ) - }) - - it('has a limited public interface [ @skip-coverage ]', async () => { - publicAbi(vrfCoordinatorV2, [ - // Public constants - 'MAX_CONSUMERS', - 'MAX_NUM_WORDS', - 'MAX_REQUEST_CONFIRMATIONS', - // Owner - 'acceptOwnership', - 'transferOwnership', - 'owner', - 'getConfig', - 'getFeeConfig', - 'getFallbackWeiPerUnitLink', - 'getCurrentSubId', - 'setConfig', - 'getRequestConfig', - 'recoverFunds', - 'ownerCancelSubscription', - 'getFeeTier', - 'pendingRequestExists', - 'getTotalBalance', - // Oracle - 'requestRandomWords', - 'getCommitment', // Note we use this to check if a request is already fulfilled. - 'hashOfKey', - 'fulfillRandomWords', - 'registerProvingKey', - 'deregisterProvingKey', - 'oracleWithdraw', - // Subscription management - 'createSubscription', - 'addConsumer', - 'removeConsumer', - 'getSubscription', - 'onTokenTransfer', // Effectively the fundSubscription. - 'cancelSubscription', - 'requestSubscriptionOwnerTransfer', - 'acceptSubscriptionOwnerTransfer', - // Misc - 'typeAndVersion', - 'BLOCKHASH_STORE', - 'LINK', - 'LINK_ETH_FEED', - ]) - }) - - describe('#setConfig', async function () { - it('only owner can set', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .setConfig( - c.minimumRequestBlockConfirmations, - c.maxGasLimit, - c.stalenessSeconds, - c.gasAfterPaymentCalculation, - c.weiPerUnitLink, - [0, 0, 0, 0, 0, 0, 0, 0, 0], - ), - ).to.be.revertedWith('Only callable by owner') - // Anyone can read the config. - const resp = await vrfCoordinatorV2.connect(random).getConfig() - assert(resp[0] == c.minimumRequestBlockConfirmations) - assert(resp[1] == c.maxGasLimit) - assert(resp[2] == c.stalenessSeconds) - assert(resp[3].toString() == c.gasAfterPaymentCalculation.toString()) - }) - - it('max req confs', async function () { - await expect( - vrfCoordinatorV2 - .connect(owner) - .setConfig( - 201, - c.maxGasLimit, - c.stalenessSeconds, - c.gasAfterPaymentCalculation, - c.weiPerUnitLink, - [0, 0, 0, 0, 0, 0, 0, 0, 0], - ), - ) - .to.be.revertedWithCustomError( - vrfCoordinatorV2, - 'InvalidRequestConfirmations', - ) - .withArgs(201, 201, 200) - }) - - it('positive fallback price', async function () { - await expect( - vrfCoordinatorV2 - .connect(owner) - .setConfig( - c.minimumRequestBlockConfirmations, - c.maxGasLimit, - c.stalenessSeconds, - c.gasAfterPaymentCalculation, - 0, - [0, 0, 0, 0, 0, 0, 0, 0, 0], - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, 'InvalidLinkWeiPrice') - .withArgs(0) - await expect( - vrfCoordinatorV2 - .connect(owner) - .setConfig( - c.minimumRequestBlockConfirmations, - c.maxGasLimit, - c.stalenessSeconds, - c.gasAfterPaymentCalculation, - -1, - [0, 0, 0, 0, 0, 0, 0, 0, 0], - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, 'InvalidLinkWeiPrice') - .withArgs(-1) - }) - }) - - async function createSubscription(): Promise { - // let consumers: string[] = [await consumer.getAddress()]; - const tx = await vrfCoordinatorV2.connect(subOwner).createSubscription() - const receipt = await tx.wait() - const subId = receipt.events[0].args['subId'] - await vrfCoordinatorV2 - .connect(subOwner) - .addConsumer(subId, await consumer.getAddress()) - return subId - } - - async function createSubscriptionWithConsumers( - consumers: string[], - ): Promise { - const tx = await vrfCoordinatorV2.connect(subOwner).createSubscription() - const receipt = await tx.wait() - const subId = receipt.events[0].args['subId'] - for (let i = 0; i < consumers.length; i++) { - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, consumers[i]) - } - return subId - } - - describe('#createSubscription', async function () { - it('can create a subscription', async function () { - await expect(vrfCoordinatorV2.connect(subOwner).createSubscription()) - .to.emit(vrfCoordinatorV2, 'SubscriptionCreated') - .withArgs(1, subOwnerAddress) - const s = await vrfCoordinatorV2.getSubscription(1) - assert(s.balance.toString() == '0', 'invalid balance') - assert(s.owner == subOwnerAddress, 'invalid address') - }) - it('subscription id increments', async function () { - await expect(vrfCoordinatorV2.connect(subOwner).createSubscription()) - .to.emit(vrfCoordinatorV2, 'SubscriptionCreated') - .withArgs(1, subOwnerAddress) - await expect(vrfCoordinatorV2.connect(subOwner).createSubscription()) - .to.emit(vrfCoordinatorV2, 'SubscriptionCreated') - .withArgs(2, subOwnerAddress) - }) - it('cannot create more than the max', async function () { - const subId = createSubscriptionWithConsumers([]) - for (let i = 0; i < 100; i++) { - await vrfCoordinatorV2 - .connect(subOwner) - .addConsumer(subId, randomAddressString()) - } - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .addConsumer(subId, randomAddressString()), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `TooManyConsumers`) - }) - }) - - describe('#requestSubscriptionOwnerTransfer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription() - }) - it('rejects non-owner', async function () { - await expect( - vrfCoordinatorV2 - .connect(random) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - }) - it('owner can request transfer', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionOwnerTransferRequested') - .withArgs(subId, subOwnerAddress, randomAddress) - // Same request is a noop - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ).to.not.emit(vrfCoordinatorV2, 'SubscriptionOwnerTransferRequested') - }) - }) - - describe('#acceptSubscriptionOwnerTransfer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription() - }) - it('subscription must exist', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .acceptSubscriptionOwnerTransfer(1203123123), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidSubscription`) - }) - it('must be requested owner to accept', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ) - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .acceptSubscriptionOwnerTransfer(subId), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeRequestedOwner`) - .withArgs(randomAddress) - }) - it('requested owner can accept', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionOwnerTransferRequested') - .withArgs(subId, subOwnerAddress, randomAddress) - await expect( - vrfCoordinatorV2.connect(random).acceptSubscriptionOwnerTransfer(subId), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionOwnerTransferred') - .withArgs(subId, subOwnerAddress, randomAddress) - }) - }) - - describe('#addConsumer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription() - }) - it('subscription must exist', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .addConsumer(1203123123, randomAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidSubscription`) - }) - it('must be owner', async function () { - await expect( - vrfCoordinatorV2.connect(random).addConsumer(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - }) - it('add is idempotent', async function () { - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - }) - it('cannot add more than maximum', async function () { - // There is one consumer, add another 99 to hit the max - for (let i = 0; i < 99; i++) { - await vrfCoordinatorV2 - .connect(subOwner) - .addConsumer(subId, randomAddressString()) - } - // Adding one more should fail - // await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress); - await expect( - vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `TooManyConsumers`) - // Same is true if we first create with the maximum - const consumers: string[] = [] - for (let i = 0; i < 100; i++) { - consumers.push(randomAddressString()) - } - subId = await createSubscriptionWithConsumers(consumers) - await expect( - vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `TooManyConsumers`) - }) - it('owner can update', async function () { - await expect( - vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionConsumerAdded') - .withArgs(subId, randomAddress) - }) - }) - - describe('#removeConsumer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription() - }) - it('subscription must exist', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .removeConsumer(1203123123, randomAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidSubscription`) - }) - it('must be owner', async function () { - await expect( - vrfCoordinatorV2.connect(random).removeConsumer(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - }) - it('owner can update', async function () { - const subBefore = await vrfCoordinatorV2.getSubscription(subId) - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - await expect( - vrfCoordinatorV2.connect(subOwner).removeConsumer(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionConsumerRemoved') - .withArgs(subId, randomAddress) - const subAfter = await vrfCoordinatorV2.getSubscription(subId) - // Subscription should NOT contain the removed consumer - assert.deepEqual(subBefore.consumers, subAfter.consumers) - }) - it('can remove all consumers', async function () { - // Testing the handling of zero. - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - await vrfCoordinatorV2 - .connect(subOwner) - .removeConsumer(subId, randomAddress) - await vrfCoordinatorV2 - .connect(subOwner) - .removeConsumer(subId, await consumer.getAddress()) - // Should be empty - const subAfter = await vrfCoordinatorV2.getSubscription(subId) - assert.deepEqual(subAfter.consumers, []) - }) - }) - - describe('#cancelSubscription', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription() - }) - it('subscription must exist', async function () { - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(1203123123, subOwnerAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidSubscription`) - }) - it('must be owner', async function () { - await expect( - vrfCoordinatorV2 - .connect(random) - .cancelSubscription(subId, subOwnerAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - }) - it('can cancel', async function () { - await linkToken - .connect(subOwner) - .transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionCanceled') - .withArgs(subId, randomAddress, BigNumber.from('1000')) - const randomBalance = await linkToken.balanceOf(randomAddress) - assert.equal(randomBalance.toString(), '1000000000000001000') - await expect( - vrfCoordinatorV2.connect(subOwner).getSubscription(subId), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, 'InvalidSubscription') - }) - it('can add same consumer after canceling', async function () { - await linkToken - .connect(subOwner) - .transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - await vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(subId, randomAddress) - subId = await createSubscription() - // The cancel should have removed this consumer, so we can add it again. - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - }) - it('cannot cancel with pending req', async function () { - await linkToken - .connect(subOwner) - .transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - await vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey) - await vrfCoordinatorV2.connect(owner).reg - const kh = await vrfCoordinatorV2.hashOfKey(testKey) - await vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000000, // callbackGasLimit - 1, // numWords - ) - // Should revert with outstanding requests - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(subId, randomAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, 'PendingRequestExists') - // However the owner is able to cancel - // funds go to the sub owner. - await expect( - vrfCoordinatorV2.connect(owner).ownerCancelSubscription(subId), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionCanceled') - .withArgs(subId, subOwnerAddress, BigNumber.from('1000')) - }) - }) - - describe('#recoverFunds', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription() - }) - - // Note we can't test the oracleWithdraw without fulfilling a request, so leave - // that coverage to the go tests. - it('function that should change internal balance do', async function () { - type bf = [() => Promise, BigNumber] - const balanceChangingFns: Array = [ - [ - async function () { - const s = ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]) - await linkToken - .connect(subOwner) - .transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000'), - s, - ) - }, - BigNumber.from('1000'), - ], - [ - async function () { - await vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(subId, randomAddress) - }, - BigNumber.from('-1000'), - ], - ] - for (const [fn, expectedBalanceChange] of balanceChangingFns) { - const startingBalance = await vrfCoordinatorV2.getTotalBalance() - await fn() - const endingBalance = await vrfCoordinatorV2.getTotalBalance() - assert( - endingBalance.sub(startingBalance).toString() == - expectedBalanceChange.toString(), - ) - } - }) - it('only owner can recover', async function () { - await expect( - vrfCoordinatorV2.connect(subOwner).recoverFunds(randomAddress), - ).to.be.revertedWith(`Only callable by owner`) - }) - - it('owner can recover link transferred', async function () { - // Set the internal balance - assert(BigNumber.from('0'), linkToken.balanceOf(randomAddress)) - const s = ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]) - await linkToken - .connect(subOwner) - .transferAndCall(vrfCoordinatorV2.address, BigNumber.from('1000'), s) - // Circumvent internal balance - await linkToken - .connect(subOwner) - .transfer(vrfCoordinatorV2.address, BigNumber.from('1000')) - // Should recover this 1000 - await expect(vrfCoordinatorV2.connect(owner).recoverFunds(randomAddress)) - .to.emit(vrfCoordinatorV2, 'FundsRecovered') - .withArgs(randomAddress, BigNumber.from('1000')) - assert(BigNumber.from('1000'), linkToken.balanceOf(randomAddress)) - }) - }) - - it('subscription lifecycle', async function () { - // Create subscription. - const tx = await vrfCoordinatorV2.connect(subOwner).createSubscription() - const receipt = await tx.wait() - assert(receipt.events[0].event == 'SubscriptionCreated') - assert(receipt.events[0].args['owner'] == subOwnerAddress, 'sub owner') - const subId = receipt.events[0].args['subId'] - await vrfCoordinatorV2 - .connect(subOwner) - .addConsumer(subId, await consumer.getAddress()) - - // Fund the subscription - await expect( - linkToken - .connect(subOwner) - .transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionFunded') - .withArgs(subId, BigNumber.from(0), BigNumber.from('1000000000000000000')) - - // Non-owners cannot change the consumers - await expect( - vrfCoordinatorV2.connect(random).addConsumer(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - await expect( - vrfCoordinatorV2.connect(random).removeConsumer(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - - // Non-owners cannot ask to transfer ownership - await expect( - vrfCoordinatorV2 - .connect(random) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - - // Owners can request ownership transfership - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .requestSubscriptionOwnerTransfer(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionOwnerTransferRequested') - .withArgs(subId, subOwnerAddress, randomAddress) - - // Non-requested owners cannot accept - await expect( - vrfCoordinatorV2.connect(subOwner).acceptSubscriptionOwnerTransfer(subId), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeRequestedOwner`) - .withArgs(randomAddress) - - // Requested owners can accept - await expect( - vrfCoordinatorV2.connect(random).acceptSubscriptionOwnerTransfer(subId), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionOwnerTransferred') - .withArgs(subId, subOwnerAddress, randomAddress) - - // Transfer it back to subOwner - vrfCoordinatorV2 - .connect(random) - .requestSubscriptionOwnerTransfer(subId, subOwnerAddress) - vrfCoordinatorV2.connect(subOwner).acceptSubscriptionOwnerTransfer(subId) - - // Non-owners cannot cancel - await expect( - vrfCoordinatorV2.connect(random).cancelSubscription(subId, randomAddress), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `MustBeSubOwner`) - .withArgs(subOwnerAddress) - - await expect( - vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(subId, randomAddress), - ) - .to.emit(vrfCoordinatorV2, 'SubscriptionCanceled') - .withArgs(subId, randomAddress, BigNumber.from('1000000000000000000')) - const random2Balance = await linkToken.balanceOf(randomAddress) - assert.equal(random2Balance.toString(), '2000000000000000000') - }) - - describe('#requestRandomWords', async function () { - let subId: number - let kh: string - beforeEach(async () => { - subId = await createSubscription() - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - kh = await vrfCoordinatorV2.hashOfKey(testKey) - }) - it('invalid subId', async function () { - await expect( - vrfCoordinatorV2.connect(random).requestRandomWords( - kh, // keyhash - 12301928312, // subId - 1, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidSubscription`) - }) - it('invalid consumer', async function () { - await expect( - vrfCoordinatorV2.connect(random).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidConsumer`) - .withArgs(subId, randomAddress) - }) - it('invalid req confs', async function () { - await expect( - vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 0, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ), - ) - .to.be.revertedWithCustomError( - vrfCoordinatorV2, - `InvalidRequestConfirmations`, - ) - .withArgs(0, 1, 200) - }) - it('gas limit too high', async function () { - await linkToken.connect(subOwner).transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), // 1 link > 0.1 min. - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await expect( - vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000001, // callbackGasLimit - 1, // numWords - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `GasLimitTooBig`) - .withArgs(1000001, 1000000) - }) - - it('nonce increments', async function () { - await linkToken.connect(subOwner).transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), // 1 link > 0.1 min. - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - const r1 = await vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000000, // callbackGasLimit - 1, // numWords - ) - const r1Receipt = await r1.wait() - const seed1 = r1Receipt.events[0].args['requestId'] - const r2 = await vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000000, // callbackGasLimit - 1, // numWords - ) - const r2Receipt = await r2.wait() - const seed2 = r2Receipt.events[0].args['requestId'] - assert(seed2 != seed1) - }) - - it('emits correct log', async function () { - await linkToken.connect(subOwner).transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), // 1 link > 0.1 min. - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - const reqTx = await vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ) - const reqReceipt = await reqTx.wait() - assert(reqReceipt.events.length == 1) - const reqEvent = reqReceipt.events[0] - assert(reqEvent.event == 'RandomWordsRequested', 'wrong event name') - assert( - reqEvent.args['keyHash'] == kh, - `wrong kh ${reqEvent.args['keyHash']} ${kh}`, - ) - assert( - reqEvent.args['subId'].toString() == subId.toString(), - 'wrong subId', - ) - assert( - reqEvent.args['minimumRequestConfirmations'].toString() == - BigNumber.from(1).toString(), - 'wrong minRequestConf', - ) - assert( - reqEvent.args['callbackGasLimit'] == 1000, - 'wrong callbackGasLimit', - ) - assert(reqEvent.args['numWords'] == 1, 'wrong numWords') - assert( - reqEvent.args['sender'] == (await consumer.getAddress()), - 'wrong sender address', - ) - }) - it('add/remove consumer invariant', async function () { - await linkToken.connect(subOwner).transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), // 1 link > 0.1 min. - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await vrfCoordinatorV2.connect(subOwner).addConsumer(subId, randomAddress) - await vrfCoordinatorV2 - .connect(subOwner) - .removeConsumer(subId, randomAddress) - await expect( - vrfCoordinatorV2.connect(random).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidConsumer`) - .withArgs(subId, randomAddress) - }) - it('cancel/add subscription invariant', async function () { - await linkToken.connect(subOwner).transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), // 1 link > 0.1 min. - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await vrfCoordinatorV2 - .connect(subOwner) - .cancelSubscription(subId, randomAddress) - subId = await createSubscriptionWithConsumers([]) - // Should not succeed because consumer was previously registered - // i.e. cancel should be cleaning up correctly. - await expect( - vrfCoordinatorV2.connect(random).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidConsumer`) - .withArgs(subId, randomAddress) - }) - }) - - describe('#oracleWithdraw', async function () { - it('cannot withdraw with no balance', async function () { - await expect( - vrfCoordinatorV2 - .connect(oracle) - .oracleWithdraw(randomAddressString(), BigNumber.from('100')), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `InsufficientBalance`) - }) - }) - - describe('#calculatePaymentAmount [ @skip-coverage ]', async function () { - it('output within sensible range', async function () { - // By default, hardhat sends txes with the block limit as their gas limit. - await vrfCoordinatorV2TestHelper - .connect(oracle) - .calculatePaymentAmountTest( - BigNumber.from('0'), // Gas after payment - 0, // Fee PPM - BigNumber.from('1000000000'), // Wei per unit gas (gas price) - ) - const paymentAmount = await vrfCoordinatorV2TestHelper.getPaymentAmount() - // The gas price is 1gwei and the eth/link price is set to 300000000 wei per unit link. - // paymentAmount = 1e18*weiPerUnitGas*(gasAfterPaymentCalculation + startGas - gasleft()) / uint256(weiPerUnitLink); - // So we expect x to be in the range (few thousand gas for the call) - // 1e18*1e9*(1000 gas)/30000000 < x < 1e18*1e9*(5000 gas)/30000000 - // 3.333333333E22 < x < 1.666666667E23 - //const gss = await vrfCoordinatorV2TestHelper.getGasStart(); - assert( - paymentAmount.gt(BigNumber.from('33333333330000000000000')), - 'payment too small', - ) - assert( - paymentAmount.lt(BigNumber.from('166666666600000000000000')), - 'payment too large', - ) - }) - it('payment too large', async function () { - // Set this gas price to be astronomical 1ETH/gas - // That means the payment will be (even for 1gas) - // 1e18*1e18/30000000 - // 3.333333333E28 > 1e27 (all link in existence) - await expect( - vrfCoordinatorV2TestHelper.connect(oracle).calculatePaymentAmountTest( - BigNumber.from('0'), // Gas after payment - 0, // Fee PPM - BigNumber.from('1000000000000000000'), - ), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `PaymentTooLarge`) - }) - - it('non-positive link wei price should revert', async function () { - const mockAggregatorV3Factory = await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - owner, - ) - const vrfCoordinatorV2TestHelperFactory = await ethers.getContractFactory( - 'VRFCoordinatorV2TestHelper', - owner, - ) - const mockLinkEthZero = await mockAggregatorV3Factory.deploy(0, 0) - const vrfCoordinatorV2TestHelperZero = - await vrfCoordinatorV2TestHelperFactory.deploy(mockLinkEthZero.address) - await expect( - vrfCoordinatorV2TestHelperZero - .connect(oracle) - .calculatePaymentAmountTest( - BigNumber.from('0'), // Gas after payment - 0, // Fee PPM - BigNumber.from('1000000000000000000'), - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidLinkWeiPrice`) - .withArgs(0) - const mockLinkEthNegative = await mockAggregatorV3Factory.deploy(0, -1) - const vrfCoordinatorV2TestHelperNegative = - await vrfCoordinatorV2TestHelperFactory.deploy( - mockLinkEthNegative.address, - ) - await expect( - vrfCoordinatorV2TestHelperNegative - .connect(owner) - .calculatePaymentAmountTest( - BigNumber.from('0'), // Gas after payment - 0, // Fee PPM - BigNumber.from('1000000000000000000'), - ), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `InvalidLinkWeiPrice`) - .withArgs(-1) - }) - }) - - describe('#keyRegistration', async function () { - it('register key emits log', async function () { - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - const kh = await vrfCoordinatorV2.hashOfKey(testKey) - await expect( - vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey), - ) - .to.emit(vrfCoordinatorV2, 'ProvingKeyRegistered') - .withArgs(kh, subOwnerAddress) - const reqConfig = await vrfCoordinatorV2.getRequestConfig() - assert(reqConfig[2].length == 1) // 1 keyhash registered - }) - it('cannot re-register key', async function () { - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - const kh = await vrfCoordinatorV2.hashOfKey(testKey) - await vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey) - await expect( - vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey), - ) - .to.be.revertedWithCustomError( - vrfCoordinatorV2, - `ProvingKeyAlreadyRegistered`, - ) - .withArgs(kh) - }) - it('deregister key emits log', async function () { - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - const kh = await vrfCoordinatorV2.hashOfKey(testKey) - await vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey) - await expect(vrfCoordinatorV2.deregisterProvingKey(testKey)) - .to.emit(vrfCoordinatorV2, 'ProvingKeyDeregistered') - .withArgs(kh, subOwnerAddress) - const reqConfig = await vrfCoordinatorV2.getRequestConfig() - assert(reqConfig[2].length == 0) // 0 keyhash registered - }) - it('cannot deregister unregistered key', async function () { - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - const kh = await vrfCoordinatorV2.hashOfKey(testKey) - await expect(vrfCoordinatorV2.deregisterProvingKey(testKey)) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `NoSuchProvingKey`) - .withArgs(kh) - }) - it('can register after deregister', async function () { - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - await vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey) - await vrfCoordinatorV2.deregisterProvingKey(testKey) - await vrfCoordinatorV2.registerProvingKey(randomAddress, testKey) - }) - }) - - describe('#fulfillRandomWords', async function () { - beforeEach(async () => { - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - await vrfCoordinatorV2.registerProvingKey(subOwnerAddress, testKey) - }) - it('unregistered key should fail', async function () { - const proof = [ - [BigNumber.from('1'), BigNumber.from('3')], // pk NOT registered - [BigNumber.from('1'), BigNumber.from('2')], // gamma - BigNumber.from('1'), // c - BigNumber.from('1'), // s - BigNumber.from('1'), // seed - randomAddress, // uWitness - [BigNumber.from('1'), BigNumber.from('2')], // cGammaWitness - [BigNumber.from('1'), BigNumber.from('2')], // sHashWitness - BigNumber.from('1'), - ] // 13 words in proof - const rc = [ - 1, // blockNum - 2, // subId - 3, // callbackGasLimit - 4, // numWords - randomAddress, // sender - ] - await expect( - vrfCoordinatorV2.connect(oracle).fulfillRandomWords(proof, rc), - ) - .to.be.revertedWithCustomError(vrfCoordinatorV2, `NoSuchProvingKey`) - .withArgs( - '0xa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c', - ) - }) - it('no corresponding request', async function () { - const proof = [ - [BigNumber.from('1'), BigNumber.from('2')], // pk - [BigNumber.from('1'), BigNumber.from('2')], // gamma - BigNumber.from('1'), // c - BigNumber.from('1'), // s - BigNumber.from('1'), // seed - randomAddress, // uWitness - [BigNumber.from('1'), BigNumber.from('2')], // cGammaWitness - [BigNumber.from('1'), BigNumber.from('2')], // sHashWitness - BigNumber.from('1'), - ] // 13 words in proof - const rc = [ - 1, // blockNum - 2, // subId - 3, // callbackGasLimit - 4, // numWords - randomAddress, // sender - ] - await expect( - vrfCoordinatorV2.connect(oracle).fulfillRandomWords(proof, rc), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2, - `NoCorrespondingRequest`, - ) - }) - it('incorrect commitment wrong blocknum', async function () { - const subId = await createSubscription() - await linkToken.connect(subOwner).transferAndCall( - vrfCoordinatorV2.address, - BigNumber.from('1000000000000000000'), // 1 link > 0.1 min. - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - const testKey = [BigNumber.from('1'), BigNumber.from('2')] - const kh = await vrfCoordinatorV2.hashOfKey(testKey) - const tx = await vrfCoordinatorV2.connect(consumer).requestRandomWords( - kh, // keyhash - subId, // subId - 1, // minReqConf - 1000, // callbackGasLimit - 1, // numWords - ) - const reqReceipt = await tx.wait() - // We give it the right proof length and a valid preSeed - // but an invalid commitment - const preSeed = reqReceipt.events[0].args['preSeed'] - const proof = [ - [BigNumber.from('1'), BigNumber.from('2')], - [BigNumber.from('1'), BigNumber.from('2')], - BigNumber.from('1'), - BigNumber.from('1'), - preSeed, - randomAddress, - [BigNumber.from('1'), BigNumber.from('2')], - [BigNumber.from('1'), BigNumber.from('2')], - BigNumber.from('1'), - ] - const rc = [ - reqReceipt.blockNumber + 1, // Wrong blocknumber - subId, - 1000, - 1, - await consumer.getAddress(), - ] - await expect( - vrfCoordinatorV2.connect(oracle).fulfillRandomWords(proof, rc), - ).to.be.revertedWithCustomError(vrfCoordinatorV2, `IncorrectCommitment`) - }) - }) - - describe('#getFeeTier', async function () { - beforeEach(async () => { - await expect( - vrfCoordinatorV2 - .connect(owner) - .setConfig( - c.minimumRequestBlockConfirmations, - c.maxGasLimit, - c.stalenessSeconds, - c.gasAfterPaymentCalculation, - c.weiPerUnitLink, - [10000, 1000, 100, 10, 1, 10, 20, 30, 40], - ), - ) - }) - it('tier1', async function () { - assert((await vrfCoordinatorV2.connect(random).getFeeTier(0)) == 10000) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(5)) == 10000) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(10)) == 10000) - }) - it('tier2', async function () { - assert((await vrfCoordinatorV2.connect(random).getFeeTier(11)) == 1000) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(12)) == 1000) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(20)) == 1000) - }) - it('tier3', async function () { - assert((await vrfCoordinatorV2.connect(random).getFeeTier(21)) == 100) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(30)) == 100) - }) - it('tier4', async function () { - assert((await vrfCoordinatorV2.connect(random).getFeeTier(31)) == 10) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(40)) == 10) - }) - it('tier5', async function () { - assert((await vrfCoordinatorV2.connect(random).getFeeTier(41)) == 1) - assert((await vrfCoordinatorV2.connect(random).getFeeTier(123102)) == 1) - }) - }) - - /* - Note that all the fulfillment happy path testing is done in Go, to make use of the existing go code to produce - proofs offchain. - */ -}) diff --git a/contracts/test/v0.8/vrf/VRFCoordinatorV2Mock.test.ts b/contracts/test/v0.8/vrf/VRFCoordinatorV2Mock.test.ts deleted file mode 100644 index 5bcb2cd5fa..0000000000 --- a/contracts/test/v0.8/vrf/VRFCoordinatorV2Mock.test.ts +++ /dev/null @@ -1,349 +0,0 @@ -import { assert, expect } from 'chai' -import { BigNumber, Contract, Signer } from 'ethers' -import { ethers } from 'hardhat' - -describe('VRFCoordinatorV2Mock', () => { - let vrfCoordinatorV2Mock: Contract - let vrfConsumerV2: Contract - let linkToken: Contract - let subOwner: Signer - let random: Signer - let subOwnerAddress: string - let pointOneLink = BigNumber.from('100000000000000000') - let oneLink = BigNumber.from('1000000000000000000') - let keyhash = - '0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0' - let testConsumerAddress = '0x1111000000000000000000000000000000001111' - let testConsumerAddress2 = '0x1111000000000000000000000000000000001110' - - beforeEach(async () => { - const accounts = await ethers.getSigners() - subOwner = accounts[1] - subOwnerAddress = await subOwner.getAddress() - random = accounts[2] - - const vrfCoordinatorV2MockFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol:VRFCoordinatorV2Mock', - accounts[0], - ) - vrfCoordinatorV2Mock = await vrfCoordinatorV2MockFactory.deploy( - pointOneLink, - 1e9, // 0.000000001 LINK per gas - ) - - const ltFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - accounts[0], - ) - linkToken = await ltFactory.deploy() - - const vrfConsumerV2Factory = await ethers.getContractFactory( - 'src/v0.8/vrf/testhelpers/VRFConsumerV2.sol:VRFConsumerV2', - accounts[0], - ) - vrfConsumerV2 = await vrfConsumerV2Factory.deploy( - vrfCoordinatorV2Mock.address, - linkToken.address, - ) - }) - - async function createSubscription(): Promise { - const tx = await vrfCoordinatorV2Mock.connect(subOwner).createSubscription() - const receipt = await tx.wait() - return receipt.events[0].args['subId'] - } - - describe('#createSubscription', async function () { - it('can create a subscription', async function () { - await expect(vrfCoordinatorV2Mock.connect(subOwner).createSubscription()) - .to.emit(vrfCoordinatorV2Mock, 'SubscriptionCreated') - .withArgs(1, subOwnerAddress) - const s = await vrfCoordinatorV2Mock.getSubscription(1) - assert(s.balance.toString() == '0', 'invalid balance') - assert(s.owner == subOwnerAddress, 'invalid address') - }) - it('subscription id increments', async function () { - await expect(vrfCoordinatorV2Mock.connect(subOwner).createSubscription()) - .to.emit(vrfCoordinatorV2Mock, 'SubscriptionCreated') - .withArgs(1, subOwnerAddress) - await expect(vrfCoordinatorV2Mock.connect(subOwner).createSubscription()) - .to.emit(vrfCoordinatorV2Mock, 'SubscriptionCreated') - .withArgs(2, subOwnerAddress) - }) - }) - describe('#addConsumer', async function () { - it('can add a consumer to a subscription', async function () { - let subId = await createSubscription() - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, testConsumerAddress), - ) - .to.emit(vrfCoordinatorV2Mock, 'ConsumerAdded') - .withArgs(subId, testConsumerAddress) - let sub = await vrfCoordinatorV2Mock - .connect(subOwner) - .getSubscription(subId) - expect(sub.consumers).to.eql([testConsumerAddress]) - }) - it('cannot add a consumer to a nonexistent subscription', async function () { - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(4, testConsumerAddress), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2Mock, - 'InvalidSubscription', - ) - }) - it('cannot add more than the consumer maximum', async function () { - let subId = await createSubscription() - for (let i = 0; i < 100; i++) { - const testIncrementingAddress = BigNumber.from(i) - .add('0x1000000000000000000000000000000000000000') - .toHexString() - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, testIncrementingAddress), - ).to.emit(vrfCoordinatorV2Mock, 'ConsumerAdded') - } - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, testConsumerAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2Mock, 'TooManyConsumers') - }) - }) - describe('#removeConsumer', async function () { - it('can remove a consumer from a subscription', async function () { - let subId = await createSubscription() - for (const addr of [testConsumerAddress, testConsumerAddress2]) { - await expect( - vrfCoordinatorV2Mock.connect(subOwner).addConsumer(subId, addr), - ).to.emit(vrfCoordinatorV2Mock, 'ConsumerAdded') - } - - let sub = await vrfCoordinatorV2Mock - .connect(subOwner) - .getSubscription(subId) - expect(sub.consumers).to.eql([testConsumerAddress, testConsumerAddress2]) - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .removeConsumer(subId, testConsumerAddress), - ) - .to.emit(vrfCoordinatorV2Mock, 'ConsumerRemoved') - .withArgs(subId, testConsumerAddress) - - sub = await vrfCoordinatorV2Mock.connect(subOwner).getSubscription(subId) - expect(sub.consumers).to.eql([testConsumerAddress2]) - }) - it('cannot remove a consumer from a nonexistent subscription', async function () { - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .removeConsumer(4, testConsumerAddress), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2Mock, - 'InvalidSubscription', - ) - }) - it('cannot remove a consumer after it is already removed', async function () { - let subId = await createSubscription() - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, testConsumerAddress), - ).to.emit(vrfCoordinatorV2Mock, 'ConsumerAdded') - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .removeConsumer(subId, testConsumerAddress), - ).to.emit(vrfCoordinatorV2Mock, 'ConsumerRemoved') - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .removeConsumer(subId, testConsumerAddress), - ).to.be.revertedWithCustomError(vrfCoordinatorV2Mock, 'InvalidConsumer') - }) - }) - describe('#fundSubscription', async function () { - it('can fund a subscription', async function () { - let subId = await createSubscription() - await expect( - vrfCoordinatorV2Mock.connect(subOwner).fundSubscription(subId, oneLink), - ) - .to.emit(vrfCoordinatorV2Mock, 'SubscriptionFunded') - .withArgs(subId, 0, oneLink) - let sub = await vrfCoordinatorV2Mock - .connect(subOwner) - .getSubscription(subId) - expect(sub.balance).to.equal(oneLink) - }) - it('cannot fund a nonexistent subscription', async function () { - await expect( - vrfCoordinatorV2Mock.connect(subOwner).fundSubscription(4, oneLink), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2Mock, - 'InvalidSubscription', - ) - }) - }) - describe('#cancelSubscription', async function () { - it('can cancel a subscription', async function () { - let subId = await createSubscription() - await expect( - vrfCoordinatorV2Mock.connect(subOwner).getSubscription(subId), - ).to.not.be.reverted - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .cancelSubscription(subId, subOwner.getAddress()), - ).to.emit(vrfCoordinatorV2Mock, 'SubscriptionCanceled') - - await expect( - vrfCoordinatorV2Mock.connect(subOwner).getSubscription(subId), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2Mock, - 'InvalidSubscription', - ) - }) - }) - describe('#fulfillRandomWords', async function () { - it('fails to fulfill without being a valid consumer', async function () { - let subId = await createSubscription() - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .requestRandomWords(keyhash, subId, 3, 500_000, 2), - ).to.be.revertedWithCustomError(vrfCoordinatorV2Mock, 'InvalidConsumer') - }) - it('fails to fulfill with insufficient funds', async function () { - let subId = await createSubscription() - await vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, await subOwner.getAddress()) - - await expect( - vrfCoordinatorV2Mock - .connect(subOwner) - .requestRandomWords(keyhash, subId, 3, 500_000, 2), - ) - .to.emit(vrfCoordinatorV2Mock, 'RandomWordsRequested') - .withArgs(keyhash, 1, 100, subId, 3, 500_000, 2, subOwnerAddress) - - await expect( - vrfCoordinatorV2Mock - .connect(random) - .fulfillRandomWords(1, vrfConsumerV2.address), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2Mock, - 'InsufficientBalance', - ) - }) - it('can request and fulfill [ @skip-coverage ]', async function () { - let subId = await createSubscription() - await vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, vrfConsumerV2.address) - await expect( - vrfCoordinatorV2Mock.connect(subOwner).fundSubscription(subId, oneLink), - ).to.not.be.reverted - - // Call requestRandomWords from the consumer contract so that the requestId - // member variable on the consumer is appropriately set. - expect( - await vrfConsumerV2 - .connect(subOwner) - .requestRandomness(keyhash, subId, 3, 500_000, 2), - ) - .to.emit(vrfCoordinatorV2Mock, 'RandomWordsRequested') - .withArgs(keyhash, 1, 100, subId, 3, 500_000, 2, vrfConsumerV2.address) - - let tx = await vrfCoordinatorV2Mock - .connect(random) - .fulfillRandomWords(1, vrfConsumerV2.address) - let receipt = await tx.wait() - expect(receipt.events[0].event).to.equal('RandomWordsFulfilled') - expect(receipt.events[0].args['requestId']).to.equal(1) - expect(receipt.events[0].args['outputSeed']).to.equal(1) - expect(receipt.events[0].args['success']).to.equal(true) - assert( - receipt.events[0].args['payment'] - .sub(BigNumber.from('100119403000000000')) - .lt(BigNumber.from('10000000000')), - ) - - // Check that balance was subtracted - let sub = await vrfCoordinatorV2Mock - .connect(random) - .getSubscription(subId) - expect(sub.balance).to.equal( - oneLink.sub(receipt.events[0].args['payment']), - ) - }) - it('Correctly allows for user override of fulfillRandomWords [ @skip-coverage ]', async function () { - let subId = await createSubscription() - await vrfCoordinatorV2Mock - .connect(subOwner) - .addConsumer(subId, vrfConsumerV2.address) - await expect( - vrfCoordinatorV2Mock.connect(subOwner).fundSubscription(subId, oneLink), - ).to.not.be.reverted - - // Call requestRandomWords from the consumer contract so that the requestId - // member variable on the consumer is appropriately set. - expect( - await vrfConsumerV2 - .connect(subOwner) - .requestRandomness(keyhash, subId, 3, 500_000, 2), - ) - .to.emit(vrfCoordinatorV2Mock, 'RandomWordsRequested') - .withArgs(keyhash, 1, 100, subId, 3, 500_000, 2, vrfConsumerV2.address) - - // Call override with incorrect word count. - await expect( - vrfCoordinatorV2Mock - .connect(random) - .fulfillRandomWordsWithOverride( - 1, - vrfConsumerV2.address, - [1, 2, 3, 4, 5], - ), - ).to.be.revertedWithCustomError( - vrfCoordinatorV2Mock, - 'InvalidRandomWords', - ) - - // Call override correctly. - let tx = await vrfCoordinatorV2Mock - .connect(random) - .fulfillRandomWordsWithOverride(1, vrfConsumerV2.address, [2533, 1768]) - let receipt = await tx.wait() - expect(receipt.events[0].event).to.equal('RandomWordsFulfilled') - expect(receipt.events[0].args['requestId']).to.equal(1) - expect(receipt.events[0].args['outputSeed']).to.equal(1) - expect(receipt.events[0].args['success']).to.equal(true) - assert( - receipt.events[0].args['payment'] - .sub(BigNumber.from('100120516000000000')) - .lt(BigNumber.from('10000000000')), - ) - - // Check that balance was subtracted - let sub = await vrfCoordinatorV2Mock - .connect(random) - .getSubscription(subId) - expect(sub.balance).to.equal( - oneLink.sub(receipt.events[0].args['payment']), - ) - }) - }) -}) diff --git a/contracts/test/v0.8/vrf/VRFSubscriptionBalanceMonitor.test.ts b/contracts/test/v0.8/vrf/VRFSubscriptionBalanceMonitor.test.ts deleted file mode 100644 index ea5cdb5f39..0000000000 --- a/contracts/test/v0.8/vrf/VRFSubscriptionBalanceMonitor.test.ts +++ /dev/null @@ -1,638 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { - LinkToken, - VRFSubscriptionBalanceMonitorExposed, -} from '../../../typechain' -import * as h from '../../test-helpers/helpers' -import { BigNumber, Contract } from 'ethers' - -const OWNABLE_ERR = 'Only callable by owner' -const INVALID_WATCHLIST_ERR = `InvalidWatchList` -const PAUSED_ERR = 'Pausable: paused' -const ONLY_KEEPER_ERR = `OnlyKeeperRegistry` - -const zeroLINK = ethers.utils.parseEther('0') -const oneLINK = ethers.utils.parseEther('1') -const twoLINK = ethers.utils.parseEther('2') -const threeLINK = ethers.utils.parseEther('3') -const fiveLINK = ethers.utils.parseEther('5') -const sixLINK = ethers.utils.parseEther('6') -const tenLINK = ethers.utils.parseEther('10') -const oneHundredLINK = ethers.utils.parseEther('100') - -let lt: LinkToken -let coordinator: Contract -let bm: VRFSubscriptionBalanceMonitorExposed -let owner: SignerWithAddress -let stranger: SignerWithAddress -let keeperRegistry: SignerWithAddress - -const sub1 = BigNumber.from(1) -const sub2 = BigNumber.from(2) -const sub3 = BigNumber.from(3) -const sub4 = BigNumber.from(4) -const sub5 = BigNumber.from(5) -const sub6 = BigNumber.from(6) - -const toNums = (bigNums: BigNumber[]) => bigNums.map((n) => n.toNumber()) - -async function assertWatchlistBalances( - balance1: BigNumber, - balance2: BigNumber, - balance3: BigNumber, - balance4: BigNumber, - balance5: BigNumber, - balance6: BigNumber, -) { - await h.assertSubscriptionBalance(coordinator, sub1, balance1, 'sub 1') - await h.assertSubscriptionBalance(coordinator, sub2, balance2, 'sub 2') - await h.assertSubscriptionBalance(coordinator, sub3, balance3, 'sub 3') - await h.assertSubscriptionBalance(coordinator, sub4, balance4, 'sub 4') - await h.assertSubscriptionBalance(coordinator, sub5, balance5, 'sub 5') - await h.assertSubscriptionBalance(coordinator, sub6, balance6, 'sub 6') -} - -describe('VRFSubscriptionBalanceMonitor', () => { - beforeEach(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - stranger = accounts[1] - keeperRegistry = accounts[2] - - const bmFactory = await ethers.getContractFactory( - 'VRFSubscriptionBalanceMonitorExposed', - owner, - ) - const ltFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - owner, - ) - - const coordinatorFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/VRFCoordinatorV2.sol:VRFCoordinatorV2', - owner, - ) - - lt = await ltFactory.deploy() - coordinator = await coordinatorFactory.deploy( - lt.address, - lt.address, - lt.address, - ) // we don't use BHS or LinkEthFeed - bm = await bmFactory.deploy( - lt.address, - coordinator.address, - keeperRegistry.address, - 0, - ) - - for (let i = 0; i <= 5; i++) { - await coordinator.connect(owner).createSubscription() - } - - // Transfer LINK to stranger. - await lt.transfer(stranger.address, oneHundredLINK) - - // Fund sub 5. - await lt - .connect(owner) - .transferAndCall( - coordinator.address, - oneHundredLINK, - ethers.utils.defaultAbiCoder.encode(['uint256'], ['5']), - ) - - // Fun sub 6. - await lt - .connect(owner) - .transferAndCall( - coordinator.address, - oneHundredLINK, - ethers.utils.defaultAbiCoder.encode(['uint256'], ['6']), - ) - - await Promise.all([bm.deployed(), coordinator.deployed(), lt.deployed()]) - }) - - afterEach(async () => { - await h.reset() - }) - - describe('add funds', () => { - it('Should allow anyone to add funds', async () => { - await lt.transfer(bm.address, oneLINK) - await lt.connect(stranger).transfer(bm.address, oneLINK) - }) - }) - - describe('withdraw()', () => { - beforeEach(async () => { - const tx = await lt.connect(owner).transfer(bm.address, oneLINK) - await tx.wait() - }) - - it('Should allow the owner to withdraw', async () => { - const beforeBalance = await lt.balanceOf(owner.address) - const tx = await bm.connect(owner).withdraw(oneLINK, owner.address) - await tx.wait() - const afterBalance = await lt.balanceOf(owner.address) - assert.isTrue( - afterBalance.gt(beforeBalance), - 'balance did not increase after withdraw', - ) - }) - - it('Should emit an event', async () => { - const tx = await bm.connect(owner).withdraw(oneLINK, owner.address) - await expect(tx) - .to.emit(bm, 'FundsWithdrawn') - .withArgs(oneLINK, owner.address) - }) - - it('Should allow the owner to withdraw to anyone', async () => { - const beforeBalance = await lt.balanceOf(stranger.address) - const tx = await bm.connect(owner).withdraw(oneLINK, stranger.address) - await tx.wait() - const afterBalance = await lt.balanceOf(stranger.address) - assert.isTrue( - beforeBalance.add(oneLINK).eq(afterBalance), - 'balance did not increase after withdraw', - ) - }) - - it('Should not allow strangers to withdraw', async () => { - const tx = bm.connect(stranger).withdraw(oneLINK, owner.address) - await expect(tx).to.be.revertedWith(OWNABLE_ERR) - }) - }) - - describe('pause() / unpause()', () => { - it('Should allow owner to pause / unpause', async () => { - const pauseTx = await bm.connect(owner).pause() - await pauseTx.wait() - const unpauseTx = await bm.connect(owner).unpause() - await unpauseTx.wait() - }) - - it('Should not allow strangers to pause / unpause', async () => { - const pauseTxStranger = bm.connect(stranger).pause() - await expect(pauseTxStranger).to.be.revertedWith(OWNABLE_ERR) - const pauseTxOwner = await bm.connect(owner).pause() - await pauseTxOwner.wait() - const unpauseTxStranger = bm.connect(stranger).unpause() - await expect(unpauseTxStranger).to.be.revertedWith(OWNABLE_ERR) - }) - }) - - describe('setWatchList() / getWatchList() / getAccountInfo()', () => { - it('Should allow owner to set the watchlist', async () => { - // should start unactive - assert.isFalse((await bm.getSubscriptionInfo(sub1)).isActive) - // add first watchlist - let setTx = await bm - .connect(owner) - .setWatchList([sub1], [oneLINK], [twoLINK]) - await setTx.wait() - let watchList = await bm.getWatchList() - assert.deepEqual(toNums(watchList), toNums([sub1])) - const subInfo = await bm.getSubscriptionInfo(1) - assert.isTrue(subInfo.isActive) - expect(subInfo.minBalanceJuels).to.equal(oneLINK) - expect(subInfo.topUpAmountJuels).to.equal(twoLINK) - // add more to watchlist - setTx = await bm - .connect(owner) - .setWatchList( - [1, 2, 3], - [oneLINK, twoLINK, threeLINK], - [twoLINK, threeLINK, fiveLINK], - ) - await setTx.wait() - watchList = await bm.getWatchList() - assert.deepEqual(toNums(watchList), toNums([sub1, sub2, sub3])) - let subInfo1 = await bm.getSubscriptionInfo(sub1) - let subInfo2 = await bm.getSubscriptionInfo(sub2) - let subInfo3 = await bm.getSubscriptionInfo(sub3) - expect(subInfo1.isActive).to.be.true - expect(subInfo1.minBalanceJuels).to.equal(oneLINK) - expect(subInfo1.topUpAmountJuels).to.equal(twoLINK) - expect(subInfo2.isActive).to.be.true - expect(subInfo2.minBalanceJuels).to.equal(twoLINK) - expect(subInfo2.topUpAmountJuels).to.equal(threeLINK) - expect(subInfo3.isActive).to.be.true - expect(subInfo3.minBalanceJuels).to.equal(threeLINK) - expect(subInfo3.topUpAmountJuels).to.equal(fiveLINK) - // remove some from watchlist - setTx = await bm - .connect(owner) - .setWatchList([sub3, sub1], [threeLINK, oneLINK], [fiveLINK, twoLINK]) - await setTx.wait() - watchList = await bm.getWatchList() - assert.deepEqual(toNums(watchList), toNums([sub3, sub1])) - subInfo1 = await bm.getSubscriptionInfo(sub1) - subInfo2 = await bm.getSubscriptionInfo(sub2) - subInfo3 = await bm.getSubscriptionInfo(sub3) - expect(subInfo1.isActive).to.be.true - expect(subInfo2.isActive).to.be.false - expect(subInfo3.isActive).to.be.true - }) - - it('Should not allow duplicates in the watchlist', async () => { - const errMsg = `DuplicateSubcriptionId` - const setTx = bm - .connect(owner) - .setWatchList( - [sub1, sub2, sub1], - [oneLINK, twoLINK, threeLINK], - [twoLINK, threeLINK, fiveLINK], - ) - await expect(setTx) - .to.be.revertedWithCustomError(bm, errMsg) - .withArgs(sub1) - }) - - it('Should not allow a topUpAmountJuels les than or equal to minBalance in the watchlist', async () => { - const setTx = bm - .connect(owner) - .setWatchList( - [sub1, sub2, sub1], - [oneLINK, twoLINK, threeLINK], - [zeroLINK, twoLINK, threeLINK], - ) - await expect(setTx).to.be.revertedWithCustomError( - bm, - INVALID_WATCHLIST_ERR, - ) - }) - - it('Should not allow strangers to set the watchlist', async () => { - const setTxStranger = bm - .connect(stranger) - .setWatchList([sub1], [oneLINK], [twoLINK]) - await expect(setTxStranger).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should revert if the list lengths differ', async () => { - let tx = bm.connect(owner).setWatchList([sub1], [], [twoLINK]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - tx = bm.connect(owner).setWatchList([sub1], [oneLINK], []) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - tx = bm.connect(owner).setWatchList([], [oneLINK], [twoLINK]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should revert if any of the subIDs are zero', async () => { - let tx = bm - .connect(owner) - .setWatchList([sub1, 0], [oneLINK, oneLINK], [twoLINK, twoLINK]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - - it('Should revert if any of the top up amounts are 0', async () => { - const tx = bm - .connect(owner) - .setWatchList([sub1, sub2], [oneLINK, oneLINK], [twoLINK, zeroLINK]) - await expect(tx).to.be.revertedWithCustomError(bm, INVALID_WATCHLIST_ERR) - }) - }) - - describe('getKeeperRegistryAddress() / setKeeperRegistryAddress()', () => { - const newAddress = ethers.Wallet.createRandom().address - - it('Should initialize with the registry address provided to the constructor', async () => { - const address = await bm.s_keeperRegistryAddress() - assert.equal(address, keeperRegistry.address) - }) - - it('Should allow the owner to set the registry address', async () => { - const setTx = await bm.connect(owner).setKeeperRegistryAddress(newAddress) - await setTx.wait() - const address = await bm.s_keeperRegistryAddress() - assert.equal(address, newAddress) - }) - - it('Should not allow strangers to set the registry address', async () => { - const setTx = bm.connect(stranger).setKeeperRegistryAddress(newAddress) - await expect(setTx).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should emit an event', async () => { - const setTx = await bm.connect(owner).setKeeperRegistryAddress(newAddress) - await expect(setTx) - .to.emit(bm, 'KeeperRegistryAddressUpdated') - .withArgs(keeperRegistry.address, newAddress) - }) - }) - - describe('getMinWaitPeriodSeconds / setMinWaitPeriodSeconds()', () => { - const newWaitPeriod = BigNumber.from(1) - - it('Should initialize with the wait period provided to the constructor', async () => { - const minWaitPeriod = await bm.s_minWaitPeriodSeconds() - expect(minWaitPeriod).to.equal(0) - }) - - it('Should allow owner to set the wait period', async () => { - const setTx = await bm - .connect(owner) - .setMinWaitPeriodSeconds(newWaitPeriod) - await setTx.wait() - const minWaitPeriod = await bm.s_minWaitPeriodSeconds() - expect(minWaitPeriod).to.equal(newWaitPeriod) - }) - - it('Should not allow strangers to set the wait period', async () => { - const setTx = bm.connect(stranger).setMinWaitPeriodSeconds(newWaitPeriod) - await expect(setTx).to.be.revertedWith(OWNABLE_ERR) - }) - - it('Should emit an event', async () => { - const setTx = await bm - .connect(owner) - .setMinWaitPeriodSeconds(newWaitPeriod) - await expect(setTx) - .to.emit(bm, 'MinWaitPeriodUpdated') - .withArgs(0, newWaitPeriod) - }) - }) - - describe('checkUpkeep() / getUnderfundedSubscriptions()', () => { - beforeEach(async () => { - const setTx = await bm.connect(owner).setWatchList( - [ - sub1, // needs funds - sub5, // funded - sub2, // needs funds - sub6, // funded - sub3, // needs funds - ], - new Array(5).fill(oneLINK), - new Array(5).fill(twoLINK), - ) - await setTx.wait() - }) - - it('Should return list of subscriptions that are underfunded', async () => { - const fundTx = await lt.connect(owner).transfer( - bm.address, - sixLINK, // needs 6 total - ) - await fundTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - let [subs] = ethers.utils.defaultAbiCoder.decode(['uint64[]'], payload) - assert.deepEqual(toNums(subs), toNums([sub1, sub2, sub3])) - // checkUpkeep payload should match getUnderfundedSubscriptions() - subs = await bm.getUnderfundedSubscriptions() - assert.deepEqual(toNums(subs), toNums([sub1, sub2, sub3])) - }) - - it('Should return some results even if contract cannot fund all eligible targets', async () => { - const fundTx = await lt.connect(owner).transfer( - bm.address, - fiveLINK, // needs 6 total - ) - await fundTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - const [subs] = ethers.utils.defaultAbiCoder.decode(['uint64[]'], payload) - assert.deepEqual(toNums(subs), toNums([sub1, sub2])) - }) - - it('Should omit subscriptions that have been funded recently', async () => { - const setWaitPdTx = await bm.setMinWaitPeriodSeconds(3600) // 1 hour - const fundTx = await lt.connect(owner).transfer(bm.address, sixLINK) - await Promise.all([setWaitPdTx.wait(), fundTx.wait()]) - const block = await ethers.provider.getBlock('latest') - const setTopUpTx = await bm.setLastTopUpXXXTestOnly( - sub2, - block.timestamp - 100, - ) - await setTopUpTx.wait() - const [should, payload] = await bm.checkUpkeep('0x') - assert.isTrue(should) - const [subs] = ethers.utils.defaultAbiCoder.decode(['uint64[]'], payload) - assert.deepEqual(toNums(subs), toNums([sub1, sub3])) - }) - - it('Should revert when paused', async () => { - const tx = await bm.connect(owner).pause() - await tx.wait() - const ethCall = bm.checkUpkeep('0x') - await expect(ethCall).to.be.revertedWith(PAUSED_ERR) - }) - }) - - describe('performUpkeep()', () => { - let validPayload: string - let invalidPayload: string - - beforeEach(async () => { - validPayload = ethers.utils.defaultAbiCoder.encode( - ['uint64[]'], - [[sub1, sub2, sub3]], - ) - invalidPayload = ethers.utils.defaultAbiCoder.encode( - ['uint64[]'], - [[sub1, sub2, sub4, sub5]], - ) - const setTx = await bm.connect(owner).setWatchList( - [ - sub1, // needs funds - sub5, // funded - sub2, // needs funds - sub6, // funded - sub3, // needs funds - // sub4 - omitted - ], - new Array(5).fill(oneLINK), - new Array(5).fill(twoLINK), - ) - await setTx.wait() - }) - - it('Should revert when paused', async () => { - const pauseTx = await bm.connect(owner).pause() - await pauseTx.wait() - const performTx = bm.connect(keeperRegistry).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWith(PAUSED_ERR) - }) - - context('when partially funded', () => { - it('Should fund as many subscriptions as possible', async () => { - const fundTx = await lt.connect(owner).transfer( - bm.address, - fiveLINK, // only enough LINK to fund 2 subscriptions - ) - await fundTx.wait() - console.log((await lt.balanceOf(bm.address)).toString()) - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - - await assertWatchlistBalances( - twoLINK, - twoLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - await expect(performTx).to.emit(bm, 'TopUpSucceeded').withArgs(sub1) - await expect(performTx).to.emit(bm, 'TopUpSucceeded').withArgs(sub1) - }) - }) - - context('when fully funded', () => { - beforeEach(async () => { - const fundTx = await lt.connect(owner).transfer(bm.address, tenLINK) - await fundTx.wait() - }) - - it('Should fund the appropriate subscriptions', async () => { - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances( - twoLINK, - twoLINK, - twoLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - }) - - it('Should only fund active, underfunded subscriptions', async () => { - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(invalidPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances( - twoLINK, - twoLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - }) - - it('Should not fund subscriptions that have been funded recently', async () => { - const setWaitPdTx = await bm.setMinWaitPeriodSeconds(3600) // 1 hour - await setWaitPdTx.wait() - const block = await ethers.provider.getBlock('latest') - const setTopUpTx = await bm.setLastTopUpXXXTestOnly( - sub2, - block.timestamp - 100, - ) - await setTopUpTx.wait() - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 2_500_000 }) - await performTx.wait() - await assertWatchlistBalances( - twoLINK, - zeroLINK, - twoLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - }) - - it('Should only be callable by the keeper registry contract', async () => { - let performTx = bm.connect(owner).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWithCustomError( - bm, - ONLY_KEEPER_ERR, - ) - performTx = bm.connect(stranger).performUpkeep(validPayload) - await expect(performTx).to.be.revertedWithCustomError( - bm, - ONLY_KEEPER_ERR, - ) - }) - - it('Should protect against running out of gas', async () => { - await assertWatchlistBalances( - zeroLINK, - zeroLINK, - zeroLINK, - zeroLINK, - oneHundredLINK, - oneHundredLINK, - ) - const performTx = await bm - .connect(keeperRegistry) - .performUpkeep(validPayload, { gasLimit: 130_000 }) // too little for all 3 transfers - await performTx.wait() - const balance1 = (await coordinator.getSubscription(sub1)).balance - const balance2 = (await coordinator.getSubscription(sub2)).balance - const balance3 = (await coordinator.getSubscription(sub3)).balance - const balances = [balance1, balance2, balance3].map((n) => n.toString()) - expect(balances) - .to.include(twoLINK.toString()) // expect at least 1 transfer - .to.include(zeroLINK.toString()) // expect at least 1 out of funds - }) - }) - }) - - describe('topUp()', () => { - context('when not paused', () => { - it('Should be callable by anyone', async () => { - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - await bm.connect(user).topUp([]) - } - }) - }) - context('when paused', () => { - it('Should be callable by no one', async () => { - await bm.connect(owner).pause() - const users = [owner, keeperRegistry, stranger] - for (let idx = 0; idx < users.length; idx++) { - const user = users[idx] - const tx = bm.connect(user).topUp([]) - await expect(tx).to.be.revertedWith(PAUSED_ERR) - } - }) - }) - }) -}) diff --git a/contracts/test/v0.8/vrf/VRFV2Wrapper.test.ts b/contracts/test/v0.8/vrf/VRFV2Wrapper.test.ts deleted file mode 100644 index 54c3b5f99b..0000000000 --- a/contracts/test/v0.8/vrf/VRFV2Wrapper.test.ts +++ /dev/null @@ -1,656 +0,0 @@ -import { assert, expect } from 'chai' -import { BigNumber, BigNumberish, Signer } from 'ethers' -import { ethers } from 'hardhat' -import { reset, toBytes32String } from '../../test-helpers/helpers' -import { bigNumEquals } from '../../test-helpers/matchers' -import { describe } from 'mocha' -import { - LinkToken, - MockV3Aggregator, - MockV3Aggregator__factory, - VRFCoordinatorV2Mock, - VRFV2Wrapper, - VRFV2WrapperConsumerExample, - VRFV2WrapperOutOfGasConsumerExample, - VRFV2WrapperRevertingConsumerExample, -} from '../../../typechain' - -describe('VRFV2Wrapper', () => { - const pointOneLink = BigNumber.from('100000000000000000') - const pointZeroZeroThreeLink = BigNumber.from('3000000000000000') - const oneHundredLink = BigNumber.from('100000000000000000000') - const oneHundredGwei = BigNumber.from('100000000000') - const fiftyGwei = BigNumber.from('50000000000') - - // Configuration - - // This value is the worst-case gas overhead from the wrapper contract under the following - // conditions, plus some wiggle room: - // - 10 words requested - // - Refund issued to consumer - const wrapperGasOverhead = BigNumber.from(60_000) - const coordinatorGasOverhead = BigNumber.from(52_000) - const wrapperPremiumPercentage = 10 - const maxNumWords = 10 - const weiPerUnitLink = pointZeroZeroThreeLink - const flatFee = pointOneLink - - let wrapper: VRFV2Wrapper - let coordinator: VRFCoordinatorV2Mock - let link: LinkToken - let wrongLink: LinkToken - let linkEthFeed: MockV3Aggregator - let consumer: VRFV2WrapperConsumerExample - let consumerWrongLink: VRFV2WrapperConsumerExample - let consumerRevert: VRFV2WrapperRevertingConsumerExample - let consumerOutOfGas: VRFV2WrapperOutOfGasConsumerExample - - let owner: Signer - let requester: Signer - let consumerOwner: Signer - let withdrawRecipient: Signer - - // This should match implementation in VRFV2Wrapper::calculateGasPriceInternal - const calculatePrice = ( - gasLimit: BigNumberish, - _wrapperGasOverhead: BigNumberish = wrapperGasOverhead, - _coordinatorGasOverhead: BigNumberish = coordinatorGasOverhead, - _gasPriceWei: BigNumberish = oneHundredGwei, - _weiPerUnitLink: BigNumberish = weiPerUnitLink, - _wrapperPremium: BigNumberish = wrapperPremiumPercentage, - _flatFee: BigNumberish = flatFee, - ): BigNumber => { - const totalGas = BigNumber.from(0) - .add(gasLimit) - .add(_wrapperGasOverhead) - .add(_coordinatorGasOverhead) - const baseFee = BigNumber.from('1000000000000000000') - .mul(_gasPriceWei) - .mul(totalGas) - .div(_weiPerUnitLink) - const withPremium = baseFee - .mul(BigNumber.from(100).add(_wrapperPremium)) - .div(100) - return withPremium.add(_flatFee) - } - - before(async () => { - await reset() - }) - - beforeEach(async () => { - const accounts = await ethers.getSigners() - owner = accounts[0] - requester = accounts[1] - consumerOwner = accounts[2] - withdrawRecipient = accounts[3] - - const coordinatorFactory = await ethers.getContractFactory( - 'VRFCoordinatorV2Mock', - owner, - ) - coordinator = await coordinatorFactory.deploy( - pointOneLink, - 1e9, // 0.000000001 LINK per gas - ) - - const linkEthFeedFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - owner, - )) as unknown as MockV3Aggregator__factory - linkEthFeed = await linkEthFeedFactory.deploy(18, weiPerUnitLink) // 1 LINK = 0.003 ETH - - const linkFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - owner, - ) - link = await linkFactory.deploy() - wrongLink = await linkFactory.deploy() - - const wrapperFactory = await ethers.getContractFactory( - 'VRFV2Wrapper', - owner, - ) - wrapper = await wrapperFactory.deploy( - link.address, - linkEthFeed.address, - coordinator.address, - ) - - const consumerFactory = await ethers.getContractFactory( - 'VRFV2WrapperConsumerExample', - consumerOwner, - ) - consumer = await consumerFactory.deploy(link.address, wrapper.address) - consumerWrongLink = await consumerFactory.deploy( - wrongLink.address, - wrapper.address, - ) - consumerRevert = await consumerFactory.deploy(link.address, wrapper.address) - - const revertingConsumerFactory = await ethers.getContractFactory( - 'VRFV2WrapperRevertingConsumerExample', - consumerOwner, - ) - consumerRevert = await revertingConsumerFactory.deploy( - link.address, - wrapper.address, - ) - - const outOfGasConsumerFactory = await ethers.getContractFactory( - 'VRFV2WrapperOutOfGasConsumerExample', - consumerOwner, - ) - consumerOutOfGas = await outOfGasConsumerFactory.deploy( - link.address, - wrapper.address, - ) - }) - - const configure = async (): Promise => { - await expect( - wrapper - .connect(owner) - .setConfig( - wrapperGasOverhead, - coordinatorGasOverhead, - wrapperPremiumPercentage, - toBytes32String('keyHash'), - maxNumWords, - ), - ).to.not.be.reverted - } - - const fund = async (address: string, amount: BigNumber): Promise => { - await expect(link.connect(owner).transfer(address, amount)).to.not.be - .reverted - } - - const fundSub = async (): Promise => { - await expect(coordinator.connect(owner).fundSubscription(1, oneHundredLink)) - .to.not.be.reverted - } - - describe('calculatePrice', async () => { - // Note: This is a meta-test for the calculatePrice func above. It is then assumed correct for - // the remainder of the tests - it('can calculate price at 50 gwei, 100k limit', async () => { - const result = calculatePrice( - 100_000, - wrapperGasOverhead, - coordinatorGasOverhead, - fiftyGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - bigNumEquals(BigNumber.from('3986666666666666666'), result) - }) - - it('can calculate price at 50 gwei, 200k limit', async () => { - const result = calculatePrice( - 200_000, - wrapperGasOverhead, - coordinatorGasOverhead, - fiftyGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - bigNumEquals(BigNumber.from('5820000000000000000'), result) - }) - - it('can calculate price at 200 gwei, 100k limit', async () => { - const result = calculatePrice( - 200_000, - wrapperGasOverhead, - coordinatorGasOverhead, - oneHundredGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - bigNumEquals(BigNumber.from('11540000000000000000'), result) - }) - - it('can calculate price at 200 gwei, 100k limit, 25% premium', async () => { - const result = calculatePrice( - 200_000, - wrapperGasOverhead, - coordinatorGasOverhead, - oneHundredGwei, - weiPerUnitLink, - 25, - flatFee, - ) - bigNumEquals(BigNumber.from('13100000000000000000'), result) - }) - }) - - describe('#setConfig/#getConfig', async () => { - it('can be configured', async () => { - await configure() - - const resp = await wrapper.connect(requester).getConfig() - bigNumEquals(BigNumber.from('4000000000000000'), resp[0]) // fallbackWeiPerUnitLink - bigNumEquals(2_700, resp[1]) // stalenessSeconds - bigNumEquals(BigNumber.from('100000'), resp[2]) // fulfillmentFlatFeeLinkPPM - bigNumEquals(wrapperGasOverhead, resp[3]) - bigNumEquals(coordinatorGasOverhead, resp[4]) - bigNumEquals(wrapperPremiumPercentage, resp[5]) - assert.equal(resp[6], toBytes32String('keyHash')) - bigNumEquals(10, resp[7]) - }) - - it('can be reconfigured', async () => { - await configure() - - await expect( - wrapper.connect(owner).setConfig( - 140_000, // wrapperGasOverhead - 195_000, // coordinatorGasOverhead - 9, // wrapperPremiumPercentage - toBytes32String('keyHash2'), // keyHash - 9, // maxNumWords - ), - ).to.not.be.reverted - - const resp = await wrapper.connect(requester).getConfig() - bigNumEquals(BigNumber.from('4000000000000000'), resp[0]) // fallbackWeiPerUnitLink - bigNumEquals(2_700, resp[1]) // stalenessSeconds - bigNumEquals(BigNumber.from('100000'), resp[2]) // fulfillmentFlatFeeLinkPPM - bigNumEquals(140_000, resp[3]) // wrapperGasOverhead - bigNumEquals(195_000, resp[4]) // coordinatorGasOverhead - bigNumEquals(9, resp[5]) // wrapperPremiumPercentage - assert.equal(resp[6], toBytes32String('keyHash2')) // keyHash - bigNumEquals(9, resp[7]) // maxNumWords - }) - - it('cannot be configured by a non-owner', async () => { - await expect( - wrapper.connect(requester).setConfig( - 10_000, // wrapperGasOverhead - 10_000, // coordinatorGasOverhead - 10, // wrapperPremiumPercentage - toBytes32String('keyHash'), // keyHash - 10, // maxNumWords - ), - ).to.be.reverted - }) - }) - describe('#calculatePrice', async () => { - it('cannot calculate price when not configured', async () => { - await expect(wrapper.connect(requester).calculateRequestPrice(100_000)).to - .be.reverted - }) - it('can calculate price at 50 gwei, 100k gas', async () => { - await configure() - const expected = calculatePrice( - 100_000, - wrapperGasOverhead, - coordinatorGasOverhead, - fiftyGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - const resp = await wrapper - .connect(requester) - .calculateRequestPrice(100_000, { gasPrice: fiftyGwei }) - bigNumEquals(expected, resp) - }) - - it('can calculate price at 100 gwei, 100k gas', async () => { - await configure() - const expected = calculatePrice( - 100_000, - wrapperGasOverhead, - coordinatorGasOverhead, - oneHundredGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - const resp = await wrapper - .connect(requester) - .calculateRequestPrice(100_000, { gasPrice: oneHundredGwei }) - bigNumEquals(expected, resp) - }) - - it('can calculate price at 100 gwei, 200k gas', async () => { - await configure() - const expected = calculatePrice( - 200_000, - wrapperGasOverhead, - coordinatorGasOverhead, - oneHundredGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - const resp = await wrapper - .connect(requester) - .calculateRequestPrice(200_000, { gasPrice: oneHundredGwei }) - bigNumEquals(expected, resp) - }) - }) - - describe('#estimatePrice', async () => { - it('cannot estimate price when not configured', async () => { - await expect( - wrapper - .connect(requester) - .estimateRequestPrice(100_000, oneHundredGwei), - ).to.be.reverted - }) - it('can estimate price at 50 gwei, 100k gas', async () => { - await configure() - const expected = calculatePrice( - 100_000, - wrapperGasOverhead, - coordinatorGasOverhead, - fiftyGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - const resp = await wrapper - .connect(requester) - .estimateRequestPrice(100_000, fiftyGwei) - bigNumEquals(expected, resp) - }) - - it('can estimate price at 100 gwei, 100k gas', async () => { - await configure() - const expected = calculatePrice( - 100_000, - wrapperGasOverhead, - coordinatorGasOverhead, - oneHundredGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - const resp = await wrapper - .connect(requester) - .estimateRequestPrice(100_000, oneHundredGwei) - bigNumEquals(expected, resp) - }) - - it('can estimate price at 100 gwei, 200k gas', async () => { - await configure() - const expected = calculatePrice( - 200_000, - wrapperGasOverhead, - coordinatorGasOverhead, - oneHundredGwei, - weiPerUnitLink, - wrapperPremiumPercentage, - flatFee, - ) - const resp = await wrapper - .connect(requester) - .estimateRequestPrice(200_000, oneHundredGwei) - bigNumEquals(expected, resp) - }) - }) - - describe('#onTokenTransfer/#fulfillRandomWords', async () => { - it('cannot request randomness when not configured', async () => { - await expect( - consumer.connect(consumerOwner).makeRequest(80_000, 3, 2, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.be.reverted - }) - it('can only be called through LinkToken', async () => { - configure() - await expect( - wrongLink - .connect(owner) - .transfer(consumerWrongLink.address, oneHundredLink, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.not.be.reverted - await expect( - consumerWrongLink.connect(consumerOwner).makeRequest(80_000, 3, 2, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.be.reverted - }) - it('can request and fulfill randomness', async () => { - await configure() - await fund(consumer.address, oneHundredLink) - await fundSub() - - await expect( - consumer.connect(consumerOwner).makeRequest(100_000, 3, 1, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.emit(coordinator, 'RandomWordsRequested') - - const price = calculatePrice(100_000) - - // Check that the wrapper has the paid amount - bigNumEquals(price, await link.balanceOf(wrapper.address)) - - const { paid, fulfilled } = await consumer.s_requests(1 /* requestId */) - bigNumEquals(price, paid) - expect(fulfilled).to.be.false - - // fulfill the request - await expect( - coordinator - .connect(owner) - .fulfillRandomWordsWithOverride(1, wrapper.address, [123], { - gasLimit: 1_000_000, - }), - ) - .to.emit(coordinator, 'RandomWordsFulfilled') - .to.emit(consumer, 'WrappedRequestFulfilled') - .withArgs(1, [123], BigNumber.from(price)) - - const expectedBalance = price - const diff = expectedBalance - .sub(await link.balanceOf(wrapper.address)) - .abs() - expect(diff.lt(pointOneLink)).to.be.true - }) - it('does not revert if consumer runs out of gas', async () => { - await configure() - await fund(consumerOutOfGas.address, oneHundredLink) - await fundSub() - - await expect( - consumerOutOfGas.connect(consumerOwner).makeRequest(100_000, 3, 1, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.emit(coordinator, 'RandomWordsRequested') - - const price = calculatePrice(100_000) - - // Check that the wrapper has the paid amount - bigNumEquals(price, await link.balanceOf(wrapper.address)) - - // fulfill the request - await expect( - coordinator - .connect(owner) - .fulfillRandomWordsWithOverride(1, wrapper.address, [123], { - gasLimit: 1_000_000, - }), - ) - .to.emit(coordinator, 'RandomWordsFulfilled') - .to.emit(wrapper, 'WrapperFulfillmentFailed') - }) - it('does not revert if consumer reverts', async () => { - await configure() - await fund(consumerRevert.address, oneHundredLink) - await fundSub() - - await expect( - consumerRevert.connect(consumerOwner).makeRequest(100_000, 3, 1, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.emit(coordinator, 'RandomWordsRequested') - - const price = calculatePrice(100_000) - - // Check that the wrapper has the paid amount - bigNumEquals(price, await link.balanceOf(wrapper.address)) - - // fulfill the request - await expect( - coordinator - .connect(owner) - .fulfillRandomWordsWithOverride(1, wrapper.address, [123]), - ) - .to.emit(coordinator, 'RandomWordsFulfilled') - .to.emit(wrapper, 'WrapperFulfillmentFailed') - - const expectedBalance = price - const diff = expectedBalance - .sub(await link.balanceOf(wrapper.address)) - .abs() - - expect(diff.lt(pointOneLink)).to.be.true - }) - }) - describe('#disable/#enable', async () => { - it('can only calculate price when enabled', async () => { - await configure() - - await expect(wrapper.connect(owner).disable()).to.not.be.reverted - await expect( - wrapper.connect(consumerOwner).calculateRequestPrice(100_000, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.be.reverted - - await expect(wrapper.connect(owner).enable()).to.not.be.reverted - await expect( - wrapper.connect(consumerOwner).calculateRequestPrice(100_000, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.not.be.reverted - }) - - it('can only estimate price when enabled', async () => { - await configure() - - await expect(wrapper.connect(owner).disable()).to.not.be.reverted - await expect( - wrapper - .connect(consumerOwner) - .estimateRequestPrice(100_000, oneHundredGwei), - ).to.be.reverted - - await expect(wrapper.connect(owner).enable()).to.not.be.reverted - await expect( - wrapper - .connect(consumerOwner) - .estimateRequestPrice(100_000, oneHundredGwei), - ).to.not.be.reverted - }) - - it('can be configured while disabled', async () => { - await expect(wrapper.connect(owner).disable()).to.not.be.reverted - await configure() - }) - - it('can only request randomness when enabled', async () => { - await configure() - await fund(consumer.address, oneHundredLink) - await fundSub() - - await expect(wrapper.connect(owner).disable()).to.not.be.reverted - await expect( - consumer.connect(consumerOwner).makeRequest(100_000, 3, 1, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.be.reverted - - await expect(wrapper.connect(owner).enable()).to.not.be.reverted - await expect( - consumer.connect(consumerOwner).makeRequest(100_000, 3, 1, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.not.be.reverted - }) - - it('can fulfill randomness when disabled', async () => { - await configure() - await fund(consumer.address, oneHundredLink) - await fundSub() - - await expect( - consumer.connect(consumerOwner).makeRequest(100_000, 3, 1, { - gasPrice: oneHundredGwei, - gasLimit: 1_000_000, - }), - ).to.not.be.reverted - await expect(wrapper.connect(owner).disable()).to.not.be.reverted - - await expect( - coordinator - .connect(owner) - .fulfillRandomWordsWithOverride(1, wrapper.address, [123], { - gasLimit: 1_000_000, - }), - ) - .to.emit(coordinator, 'RandomWordsFulfilled') - .to.emit(consumer, 'WrappedRequestFulfilled') - }) - }) - - describe('#withdraw', async () => { - it('can withdraw funds to the owner', async () => { - await configure() - await fund(wrapper.address, oneHundredLink) - const recipientAddress = await withdrawRecipient.getAddress() - - // Withdraw half the funds - await expect( - wrapper - .connect(owner) - .withdraw(recipientAddress, oneHundredLink.div(2)), - ).to.not.be.reverted - bigNumEquals( - oneHundredLink.div(2), - await link.balanceOf(recipientAddress), - ) - bigNumEquals(oneHundredLink.div(2), await link.balanceOf(wrapper.address)) - - // Withdraw the rest - await expect( - wrapper - .connect(owner) - .withdraw(recipientAddress, oneHundredLink.div(2)), - ).to.not.be.reverted - bigNumEquals(oneHundredLink, await link.balanceOf(recipientAddress)) - bigNumEquals(0, await link.balanceOf(wrapper.address)) - }) - - it('cannot withdraw funds to non owners', async () => { - await configure() - await fund(wrapper.address, oneHundredLink) - const recipientAddress = await withdrawRecipient.getAddress() - - await expect( - wrapper - .connect(consumerOwner) - .withdraw(recipientAddress, oneHundredLink.div(2)), - ).to.be.reverted - }) - }) -}) diff --git a/core/bridges/bridge_type.go b/core/bridges/bridge_type.go index b2e86df4b9..26f81a8c97 100644 --- a/core/bridges/bridge_type.go +++ b/core/bridges/bridge_type.go @@ -199,3 +199,10 @@ func (t *BridgeName) Scan(value interface{}) error { *t = BridgeName(temp) return nil } + +type BridgeResponse struct { + DotID string + SpecID int32 + Value []byte + FinishedAt time.Time +} diff --git a/core/bridges/cache.go b/core/bridges/cache.go new file mode 100644 index 0000000000..4b5a655244 --- /dev/null +++ b/core/bridges/cache.go @@ -0,0 +1,272 @@ +package bridges + +import ( + "context" + "database/sql" + "errors" + "fmt" + "sync" + "time" + + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/utils" +) + +const ( + CacheServiceName = "BridgeCache" + DefaultUpsertInterval = 5 * time.Second +) + +type Cache struct { + // dependencies and configurations + ORM + lggr logger.Logger + interval time.Duration + + // service state + services.StateMachine + wg sync.WaitGroup + chStop services.StopChan + + // data state + bridgeTypesCache sync.Map + bridgeLastValueCache map[string]BridgeResponse + mu sync.RWMutex +} + +var _ ORM = (*Cache)(nil) +var _ services.Service = (*Cache)(nil) + +func NewCache(base ORM, lggr logger.Logger, upsertInterval time.Duration) *Cache { + return &Cache{ + ORM: base, + lggr: lggr.Named(CacheServiceName), + interval: upsertInterval, + chStop: make(chan struct{}), + bridgeLastValueCache: make(map[string]BridgeResponse), + } +} + +func (c *Cache) WithDataSource(ds sqlutil.DataSource) ORM { + return NewCache(NewORM(ds), c.lggr, c.interval) +} + +func (c *Cache) FindBridge(ctx context.Context, name BridgeName) (BridgeType, error) { + if bridgeType, ok := c.bridgeTypesCache.Load(name); ok { + return bridgeType.(BridgeType), nil + } + + ormResult, err := c.ORM.FindBridge(ctx, name) + if err == nil { + c.bridgeTypesCache.Store(ormResult.Name, ormResult) + } + + return ormResult, err +} + +func (c *Cache) FindBridges(ctx context.Context, names []BridgeName) ([]BridgeType, error) { + if len(names) == 0 { + return nil, errors.New("at least one bridge name is required") + } + + var ( + allFoundBts []BridgeType + searchNames []BridgeName + ) + + for _, n := range names { + if bridgeType, ok := c.bridgeTypesCache.Load(n); ok { + allFoundBts = append(allFoundBts, bridgeType.(BridgeType)) + + continue + } + + searchNames = append(searchNames, n) + } + + if len(allFoundBts) == len(names) { + return allFoundBts, nil + } + + bts, err := c.ORM.FindBridges(ctx, searchNames) + if err != nil { + return nil, err + } + + for _, bt := range bts { + c.bridgeTypesCache.Store(bt.Name, bt) + } + + allFoundBts = append(allFoundBts, bts...) + if len(allFoundBts) != len(names) { + return nil, fmt.Errorf("not all bridges exist, asked for %v, exists %v", names, allFoundBts) + } + + return allFoundBts, nil +} + +func (c *Cache) DeleteBridgeType(ctx context.Context, bt *BridgeType) error { + err := c.ORM.DeleteBridgeType(ctx, bt) + if err != nil { + if !errors.Is(err, sql.ErrNoRows) { + return err + } + } + + // We delete regardless of the rows affected, in case it gets out of sync + c.bridgeTypesCache.Delete(bt.Name) + + return err +} + +func (c *Cache) BridgeTypes(ctx context.Context, offset int, limit int) ([]BridgeType, int, error) { + return c.ORM.BridgeTypes(ctx, offset, limit) +} + +func (c *Cache) CreateBridgeType(ctx context.Context, bt *BridgeType) error { + err := c.ORM.CreateBridgeType(ctx, bt) + if err != nil { + return err + } + + c.bridgeTypesCache.Store(bt.Name, *bt) + + return nil +} + +func (c *Cache) UpdateBridgeType(ctx context.Context, bt *BridgeType, btr *BridgeTypeRequest) error { + if err := c.ORM.UpdateBridgeType(ctx, bt, btr); err != nil { + return err + } + + c.bridgeTypesCache.Store(bt.Name, *bt) + + return nil +} + +func (c *Cache) GetCachedResponse(ctx context.Context, dotId string, specId int32, maxElapsed time.Duration) ([]byte, error) { + // prefer to get latest value from cache + cached, inCache := c.latestValue(dotId, specId) + if inCache && cached.FinishedAt.After(time.Now().Add(-maxElapsed)) { + return cached.Value, nil + } + + response, finishedAt, err := c.ORM.GetCachedResponseWithFinished(ctx, dotId, specId, maxElapsed) + if err != nil { + return nil, err + } + + c.setValue(dotId, specId, BridgeResponse{ + DotID: dotId, + SpecID: specId, + Value: response, + FinishedAt: finishedAt, + }) + + return response, nil +} + +func (c *Cache) UpsertBridgeResponse(ctx context.Context, dotId string, specId int32, response []byte) error { + upsertTime := time.Now() + + // catch the rare case of a save race + cached, inCache := c.latestValue(dotId, specId) + if inCache && cached.FinishedAt.After(upsertTime) { + return nil + } + + c.setValue(dotId, specId, BridgeResponse{ + DotID: dotId, + SpecID: specId, + Value: response, + FinishedAt: upsertTime, + }) + + return nil +} + +func (c *Cache) Start(_ context.Context) error { + return c.StartOnce(CacheServiceName, func() error { + c.wg.Add(1) + + go c.run() + + return nil + }) +} + +func (c *Cache) Close() error { + return c.StopOnce(CacheServiceName, func() error { + close(c.chStop) + c.wg.Wait() + + return nil + }) +} + +func (c *Cache) HealthReport() map[string]error { + return map[string]error{c.Name(): c.Healthy()} +} + +func (c *Cache) Name() string { + return c.lggr.Name() +} + +func (c *Cache) run() { + defer c.wg.Done() + + for { + timer := time.NewTimer(utils.WithJitter(c.interval)) + + select { + case <-timer.C: + c.doBulkUpsert() + case <-c.chStop: + timer.Stop() + + return + } + } +} + +func (c *Cache) doBulkUpsert() { + c.mu.RLock() + values := maps.Values(c.bridgeLastValueCache) + c.mu.RUnlock() + + if len(values) == 0 { + return + } + + ctx, cancel := c.chStop.NewCtx() + defer cancel() + + if err := c.ORM.BulkUpsertBridgeResponse(ctx, values); err != nil { + c.lggr.Warnf("bulk upsert of bridge responses failed: %s", err.Error()) + } +} + +func (c *Cache) latestValue(dotId string, specId int32) (BridgeResponse, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + + cached, inCache := c.bridgeLastValueCache[responseKey(dotId, specId)] + + return cached, inCache +} + +func (c *Cache) setValue(dotId string, specId int32, resp BridgeResponse) { + c.mu.Lock() + defer c.mu.Unlock() + + c.bridgeLastValueCache[responseKey(dotId, specId)] = resp +} + +func responseKey(dotId string, specId int32) string { + return fmt.Sprintf("%s||%d", dotId, specId) +} diff --git a/core/bridges/cache_test.go b/core/bridges/cache_test.go new file mode 100644 index 0000000000..832a7d5540 --- /dev/null +++ b/core/bridges/cache_test.go @@ -0,0 +1,202 @@ +package bridges_test + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/bridges/mocks" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestBridgeCache_Type(t *testing.T) { + t.Parallel() + + t.Run("loads bridge from data source - single", func(t *testing.T) { + t.Parallel() + + mORM := new(mocks.ORM) + lggr, _ := logger.NewLogger() + cache := bridges.NewCache(mORM, lggr, bridges.DefaultUpsertInterval) + + bridge := bridges.BridgeName("test") + expected := bridges.BridgeType{ + Name: bridge, + } + + // first call to find should fallthrough to data source + mORM.On("FindBridge", mock.Anything, bridge).Return(expected, nil) + result, err := cache.FindBridge(context.Background(), bridge) + + require.NoError(t, err) + assert.Equal(t, expected, result) + + // calling find again should return from cache + result, err = cache.FindBridge(context.Background(), bridge) + + require.NoError(t, err) + assert.Equal(t, expected, result) + }) + + t.Run("loads bridge from data source - multiple", func(t *testing.T) { + t.Parallel() + + mORM := new(mocks.ORM) + lggr, _ := logger.NewLogger() + cache := bridges.NewCache(mORM, lggr, bridges.DefaultUpsertInterval) + + ctx := context.Background() + nameA := bridges.BridgeName("A") + nameB := bridges.BridgeName("B") + nameC := bridges.BridgeName("C") + + initialExpected := []bridges.BridgeType{ + {Name: nameA}, + {Name: nameB}, + } + finalExpected := append(initialExpected, bridges.BridgeType{Name: nameC}) + + mORM.On("FindBridges", mock.Anything, []bridges.BridgeName{nameA, nameB}).Return(initialExpected, nil) + types, err := cache.FindBridges(ctx, []bridges.BridgeName{nameA, nameB}) + + require.NoError(t, err) + assert.Equal(t, initialExpected, types) + + // second call to FindBridges only includes the value not in the cache + mORM.On("FindBridges", mock.Anything, []bridges.BridgeName{nameC}). + Return([]bridges.BridgeType{{Name: nameC}}, nil) + + types, err = cache.FindBridges(ctx, []bridges.BridgeName{nameA, nameB, nameC}) + + require.NoError(t, err) + assert.Equal(t, finalExpected, types) + }) + + t.Run("creates, updates, and deletes bridge", func(t *testing.T) { + t.Parallel() + + mORM := new(mocks.ORM) + lggr, _ := logger.NewLogger() + cache := bridges.NewCache(mORM, lggr, bridges.DefaultUpsertInterval) + + ctx := context.Background() + bridge := bridges.BridgeName("test") + expected := &bridges.BridgeType{ + Name: bridge, + Confirmations: 42, + } + + mORM.On("CreateBridgeType", mock.Anything, expected).Return(nil) + assert.NoError(t, cache.CreateBridgeType(ctx, expected)) + + result, err := cache.FindBridge(ctx, bridge) + + require.NoError(t, err) + assert.Equal(t, *expected, result) + + btr := &bridges.BridgeTypeRequest{ + Confirmations: 21, + } + + mORM.On("UpdateBridgeType", mock.Anything, expected, btr).Return(nil).Run(func(args mock.Arguments) { + btp := args.Get(1).(*bridges.BridgeType) + req := args.Get(2).(*bridges.BridgeTypeRequest) + + btp.Confirmations = req.Confirmations + }) + require.NoError(t, cache.UpdateBridgeType(ctx, expected, btr)) + assert.Equal(t, btr.Confirmations, expected.Confirmations) + + result, err = cache.FindBridge(ctx, bridge) + + require.NoError(t, err) + assert.Equal(t, *expected, result) + + mORM.On("DeleteBridgeType", mock.Anything, expected).Return(nil) + require.NoError(t, cache.DeleteBridgeType(ctx, expected)) + + // bridge type is removed from cache so call to find fallsback to the data store + mORM.On("FindBridge", mock.Anything, bridge).Return(bridges.BridgeType{}, errors.New("not found")) + _, err = cache.FindBridge(ctx, bridge) + require.NotNil(t, err) + }) +} + +func TestBridgeCache_Response(t *testing.T) { + t.Parallel() + + t.Run("loads response from data source", func(t *testing.T) { + t.Parallel() + + mORM := new(mocks.ORM) + lggr, _ := logger.NewLogger() + cache := bridges.NewCache(mORM, lggr, bridges.DefaultUpsertInterval) + + ctx := context.Background() + dotId := "test" + specId := int32(42) + responseData := []byte("test") + + mORM.On("GetCachedResponseWithFinished", mock.Anything, dotId, specId, time.Second). + Return(responseData, time.Now(), nil) + + response, err := cache.GetCachedResponse(ctx, dotId, specId, time.Second) + + require.NoError(t, err) + assert.Equal(t, responseData, response) + + response, err = cache.GetCachedResponse(ctx, dotId, specId, time.Second) + + require.NoError(t, err) + assert.Equal(t, responseData, response) + }) + + t.Run("async upserts bridge response", func(t *testing.T) { + t.Parallel() + + mORM := new(mocks.ORM) + lggr, _ := logger.NewLogger() + cache := bridges.NewCache(mORM, lggr, bridges.DefaultUpsertInterval) + + t.Cleanup(func() { + require.NoError(t, cache.Close()) + }) + + require.NoError(t, cache.Start(context.Background())) + + ctx := context.Background() + dotId := "test" + specId := int32(42) + expected := []byte("test") + chBulkUpsertCalled := make(chan struct{}, 1) + + mORM.On("BulkUpsertBridgeResponse", mock.Anything, mock.Anything).Return(nil).Run(func(_ mock.Arguments) { + chBulkUpsertCalled <- struct{}{} + }) + + require.NoError(t, cache.UpsertBridgeResponse(ctx, dotId, specId, expected)) + + response, err := cache.GetCachedResponse(ctx, dotId, specId, time.Second) + + require.NoError(t, err) + assert.Equal(t, expected, response) + + timer := time.NewTimer(2 * bridges.DefaultUpsertInterval) + + select { + case <-chBulkUpsertCalled: + timer.Stop() + case <-timer.C: + timer.Stop() + + t.Log("upsert interval exceeded without expected upsert") + t.FailNow() + } + }) +} diff --git a/core/bridges/mocks/orm.go b/core/bridges/mocks/orm.go index 30dfc3e33e..cda12a9045 100644 --- a/core/bridges/mocks/orm.go +++ b/core/bridges/mocks/orm.go @@ -57,6 +57,24 @@ func (_m *ORM) BridgeTypes(ctx context.Context, offset int, limit int) ([]bridge return r0, r1, r2 } +// BulkUpsertBridgeResponse provides a mock function with given fields: ctx, responses +func (_m *ORM) BulkUpsertBridgeResponse(ctx context.Context, responses []bridges.BridgeResponse) error { + ret := _m.Called(ctx, responses) + + if len(ret) == 0 { + panic("no return value specified for BulkUpsertBridgeResponse") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []bridges.BridgeResponse) error); ok { + r0 = rf(ctx, responses) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // CreateBridgeType provides a mock function with given fields: ctx, bt func (_m *ORM) CreateBridgeType(ctx context.Context, bt *bridges.BridgeType) error { ret := _m.Called(ctx, bt) @@ -312,6 +330,43 @@ func (_m *ORM) GetCachedResponse(ctx context.Context, dotId string, specId int32 return r0, r1 } +// GetCachedResponseWithFinished provides a mock function with given fields: ctx, dotId, specId, maxElapsed +func (_m *ORM) GetCachedResponseWithFinished(ctx context.Context, dotId string, specId int32, maxElapsed time.Duration) ([]byte, time.Time, error) { + ret := _m.Called(ctx, dotId, specId, maxElapsed) + + if len(ret) == 0 { + panic("no return value specified for GetCachedResponseWithFinished") + } + + var r0 []byte + var r1 time.Time + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, string, int32, time.Duration) ([]byte, time.Time, error)); ok { + return rf(ctx, dotId, specId, maxElapsed) + } + if rf, ok := ret.Get(0).(func(context.Context, string, int32, time.Duration) []byte); ok { + r0 = rf(ctx, dotId, specId, maxElapsed) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, int32, time.Duration) time.Time); ok { + r1 = rf(ctx, dotId, specId, maxElapsed) + } else { + r1 = ret.Get(1).(time.Time) + } + + if rf, ok := ret.Get(2).(func(context.Context, string, int32, time.Duration) error); ok { + r2 = rf(ctx, dotId, specId, maxElapsed) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // UpdateBridgeType provides a mock function with given fields: ctx, bt, btr func (_m *ORM) UpdateBridgeType(ctx context.Context, bt *bridges.BridgeType, btr *bridges.BridgeTypeRequest) error { ret := _m.Called(ctx, bt, btr) diff --git a/core/bridges/orm.go b/core/bridges/orm.go index 5dfb42cff5..edacdec85b 100644 --- a/core/bridges/orm.go +++ b/core/bridges/orm.go @@ -4,7 +4,6 @@ import ( "context" "database/sql" "fmt" - "sync" "time" "github.com/jmoiron/sqlx" @@ -33,13 +32,14 @@ type ORM interface { FindExternalInitiator(ctx context.Context, eia *auth.Token) (*ExternalInitiator, error) FindExternalInitiatorByName(ctx context.Context, iname string) (exi ExternalInitiator, err error) + GetCachedResponseWithFinished(ctx context.Context, dotId string, specId int32, maxElapsed time.Duration) ([]byte, time.Time, error) + BulkUpsertBridgeResponse(ctx context.Context, responses []BridgeResponse) error + WithDataSource(sqlutil.DataSource) ORM } type orm struct { ds sqlutil.DataSource - - bridgeTypesCache sync.Map } var _ ORM = (*orm)(nil) @@ -58,58 +58,33 @@ func (o *orm) transact(ctx context.Context, readOnly bool, fn func(tx *orm) erro // FindBridge looks up a Bridge by its Name. // Returns sql.ErrNoRows if name not present func (o *orm) FindBridge(ctx context.Context, name BridgeName) (bt BridgeType, err error) { - if bridgeType, ok := o.bridgeTypesCache.Load(name); ok { - return bridgeType.(BridgeType), nil - } - stmt := "SELECT * FROM bridge_types WHERE name = $1" err = o.ds.GetContext(ctx, &bt, stmt, name.String()) - if err == nil { - o.bridgeTypesCache.Store(bt.Name, bt) - } + return } // FindBridges looks up multiple bridges in a single query. // Errors unless all bridges successfully found. Requires at least one bridge. // Expects all bridges to be unique -func (o *orm) FindBridges(ctx context.Context, names []BridgeName) (bts []BridgeType, err error) { - if len(names) == 0 { - return nil, pkgerrors.Errorf("at least one bridge name is required") - } - - var allFoundBts []BridgeType - var searchNames []BridgeName - - for _, n := range names { - if bridgeType, ok := o.bridgeTypesCache.Load(n); ok { - allFoundBts = append(allFoundBts, bridgeType.(BridgeType)) - } else { - searchNames = append(searchNames, n) - } - } - - if len(allFoundBts) == len(names) { - return allFoundBts, nil - } - +func (o *orm) FindBridges(ctx context.Context, names []BridgeName) ([]BridgeType, error) { stmt := "SELECT * FROM bridge_types WHERE name IN (?)" - query, args, err := sqlx.In(stmt, searchNames) + query, args, err := sqlx.In(stmt, names) if err != nil { return nil, err } - err = o.ds.SelectContext(ctx, &bts, o.ds.Rebind(query), args...) - if err != nil { + + var bts []BridgeType + + if err = o.ds.SelectContext(ctx, &bts, o.ds.Rebind(query), args...); err != nil { return nil, err } - for _, bt := range bts { - o.bridgeTypesCache.Store(bt.Name, bt) - } - allFoundBts = append(allFoundBts, bts...) - if len(allFoundBts) != len(names) { - return nil, pkgerrors.Errorf("not all bridges exist, asked for %v, exists %v", names, allFoundBts) + + if len(bts) != len(names) { + return nil, pkgerrors.Errorf("not all bridges exist, asked for %v, exists %v", names, bts) } - return allFoundBts, nil + + return bts, nil } // DeleteBridgeType removes the bridge type @@ -119,16 +94,17 @@ func (o *orm) DeleteBridgeType(ctx context.Context, bt *BridgeType) error { if err != nil { return err } + rowsAffected, err := result.RowsAffected() if err != nil { return err } - // We delete regardless of the rows affected, in case it gets out of sync - o.bridgeTypesCache.Delete(bt.Name) + if rowsAffected == 0 { return sql.ErrNoRows } - return err + + return nil } // BridgeTypes returns bridge types ordered by name filtered limited by the @@ -161,9 +137,6 @@ func (o *orm) CreateBridgeType(ctx context.Context, bt *BridgeType) error { defer stmt.Close() return stmt.GetContext(ctx, bt, bt) }) - if err == nil { - o.bridgeTypesCache.Store(bt.Name, *bt) - } return pkgerrors.Wrap(err, "CreateBridgeType failed") } @@ -172,23 +145,43 @@ func (o *orm) CreateBridgeType(ctx context.Context, bt *BridgeType) error { func (o *orm) UpdateBridgeType(ctx context.Context, bt *BridgeType, btr *BridgeTypeRequest) error { stmt := "UPDATE bridge_types SET url = $1, confirmations = $2, minimum_contract_payment = $3 WHERE name = $4 RETURNING *" err := o.ds.GetContext(ctx, bt, stmt, btr.URL, btr.Confirmations, btr.MinimumContractPayment, bt.Name) - if err == nil { - o.bridgeTypesCache.Store(bt.Name, *bt) - } return err } -func (o *orm) GetCachedResponse(ctx context.Context, dotId string, specId int32, maxElapsed time.Duration) (response []byte, err error) { +func (o *orm) GetCachedResponse(ctx context.Context, dotId string, specId int32, maxElapsed time.Duration) ([]byte, error) { + response, _, err := o.GetCachedResponseWithFinished(ctx, dotId, specId, maxElapsed) + if err != nil { + return nil, err + } + + return response, nil +} + +func (o *orm) GetCachedResponseWithFinished(ctx context.Context, dotId string, specId int32, maxElapsed time.Duration) ([]byte, time.Time, error) { stalenessThreshold := time.Now().Add(-maxElapsed) - sql := `SELECT value FROM bridge_last_value WHERE + sql := `SELECT value, finished_at FROM bridge_last_value WHERE dot_id = $1 AND spec_id = $2 AND finished_at > ($3) ORDER BY finished_at DESC LIMIT 1;` - err = pkgerrors.Wrap(o.ds.GetContext(ctx, &response, sql, dotId, specId, stalenessThreshold), fmt.Sprintf("failed to fetch last good value for task %s spec %d", dotId, specId)) - return + + type responseType struct { + Value []byte + FinishedAt time.Time + } + + var result responseType + + if err := pkgerrors.Wrap( + o.ds.GetContext(ctx, &result, sql, dotId, specId, stalenessThreshold), + fmt.Sprintf("failed to fetch last good value for task %s spec %d", dotId, specId), + ); err != nil { + return nil, time.Now(), err + } + + return result.Value, result.FinishedAt, nil } func (o *orm) UpsertBridgeResponse(ctx context.Context, dotId string, specId int32, response []byte) error { @@ -198,7 +191,21 @@ func (o *orm) UpsertBridgeResponse(ctx context.Context, dotId string, specId int DO UPDATE SET value = $3, finished_at = $4;` _, err := o.ds.ExecContext(ctx, sql, dotId, specId, response, time.Now()) - return pkgerrors.Wrap(err, "failed to upsert bridge response") + + return err +} + +func (o *orm) BulkUpsertBridgeResponse(ctx context.Context, responses []BridgeResponse) error { + sql := `INSERT INTO bridge_last_value(dot_id, spec_id, value, finished_at) + VALUES (:dot_id, :spec_id, :value, :finished_at) + ON CONFLICT ON CONSTRAINT bridge_last_value_pkey + DO UPDATE SET value = excluded.value, finished_at = excluded.finished_at;` + + if _, err := o.ds.NamedExecContext(ctx, sql, responses); err != nil { + return err + } + + return nil } // --- External Initiator diff --git a/core/capabilities/reader.go b/core/capabilities/reader.go new file mode 100644 index 0000000000..a0b7d3d96d --- /dev/null +++ b/core/capabilities/reader.go @@ -0,0 +1,157 @@ +package capabilities + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/types" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +type remoteRegistryReader struct { + r types.ContractReader + peerWrapper p2ptypes.PeerWrapper + lggr logger.Logger +} + +var _ reader = (*remoteRegistryReader)(nil) + +type hashedCapabilityID [32]byte +type donID uint32 + +type state struct { + IDsToDONs map[donID]kcr.CapabilitiesRegistryDONInfo + IDsToNodes map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo + IDsToCapabilities map[hashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo +} + +func (r *remoteRegistryReader) LocalNode(ctx context.Context) (capabilities.Node, error) { + if r.peerWrapper.GetPeer() == nil { + return capabilities.Node{}, errors.New("unable to get peer: peerWrapper hasn't started yet") + } + + pid := r.peerWrapper.GetPeer().ID() + + readerState, err := r.state(ctx) + if err != nil { + return capabilities.Node{}, fmt.Errorf("failed to get state from registry to determine don ownership: %w", err) + } + + var workflowDON capabilities.DON + capabilityDONs := []capabilities.DON{} + for _, d := range readerState.IDsToDONs { + for _, p := range d.NodeP2PIds { + if p == pid { + if d.AcceptsWorkflows { + if workflowDON.ID == "" { + workflowDON = *toDONInfo(d) + } else { + r.lggr.Errorf("Configuration error: node %s belongs to more than one workflowDON", pid) + } + } + + capabilityDONs = append(capabilityDONs, *toDONInfo(d)) + } + } + } + + return capabilities.Node{ + PeerID: &pid, + WorkflowDON: workflowDON, + CapabilityDONs: capabilityDONs, + }, nil +} + +func (r *remoteRegistryReader) state(ctx context.Context) (state, error) { + dons := []kcr.CapabilitiesRegistryDONInfo{} + err := r.r.GetLatestValue(ctx, "CapabilitiesRegistry", "getDONs", nil, &dons) + if err != nil { + return state{}, err + } + + idsToDONs := map[donID]kcr.CapabilitiesRegistryDONInfo{} + for _, d := range dons { + idsToDONs[donID(d.Id)] = d + } + + caps := []kcr.CapabilitiesRegistryCapabilityInfo{} + err = r.r.GetLatestValue(ctx, "CapabilitiesRegistry", "getCapabilities", nil, &caps) + if err != nil { + return state{}, err + } + + idsToCapabilities := map[hashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{} + for _, c := range caps { + idsToCapabilities[c.HashedId] = c + } + + nodes := []kcr.CapabilitiesRegistryNodeInfo{} + err = r.r.GetLatestValue(ctx, "CapabilitiesRegistry", "getNodes", nil, &nodes) + if err != nil { + return state{}, err + } + + idsToNodes := map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{} + for _, node := range nodes { + idsToNodes[node.P2pId] = node + } + + return state{IDsToDONs: idsToDONs, IDsToCapabilities: idsToCapabilities, IDsToNodes: idsToNodes}, nil +} + +type contractReaderFactory interface { + NewContractReader(context.Context, []byte) (types.ContractReader, error) +} + +func newRemoteRegistryReader(ctx context.Context, lggr logger.Logger, peerWrapper p2ptypes.PeerWrapper, relayer contractReaderFactory, remoteRegistryAddress string) (*remoteRegistryReader, error) { + contractReaderConfig := evmrelaytypes.ChainReaderConfig{ + Contracts: map[string]evmrelaytypes.ChainContractReader{ + "CapabilitiesRegistry": { + ContractABI: kcr.CapabilitiesRegistryABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + "getDONs": { + ChainSpecificName: "getDONs", + }, + "getCapabilities": { + ChainSpecificName: "getCapabilities", + }, + "getNodes": { + ChainSpecificName: "getNodes", + }, + }, + }, + }, + } + + contractReaderConfigEncoded, err := json.Marshal(contractReaderConfig) + if err != nil { + return nil, err + } + + cr, err := relayer.NewContractReader(ctx, contractReaderConfigEncoded) + if err != nil { + return nil, err + } + + err = cr.Bind(ctx, []types.BoundContract{ + { + Address: remoteRegistryAddress, + Name: "CapabilitiesRegistry", + }, + }) + if err != nil { + return nil, err + } + + return &remoteRegistryReader{ + r: cr, + peerWrapper: peerWrapper, + lggr: lggr, + }, err +} diff --git a/core/capabilities/reader_test.go b/core/capabilities/reader_test.go new file mode 100644 index 0000000000..cc61628c54 --- /dev/null +++ b/core/capabilities/reader_test.go @@ -0,0 +1,286 @@ +package capabilities + +import ( + "context" + "crypto/rand" + "encoding/json" + "fmt" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/types" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +var writeChainCapability = kcr.CapabilitiesRegistryCapability{ + LabelledName: "write-chain", + Version: "1.0.1", + ResponseType: uint8(1), +} + +func startNewChainWithRegistry(t *testing.T) (*kcr.CapabilitiesRegistry, common.Address, *bind.TransactOpts, *backends.SimulatedBackend) { + owner := testutils.MustNewSimTransactor(t) + + oneEth, _ := new(big.Int).SetString("100000000000000000000", 10) + gasLimit := ethconfig.Defaults.Miner.GasCeil * 2 // 60 M blocks + + simulatedBackend := backends.NewSimulatedBackend(core.GenesisAlloc{owner.From: { + Balance: oneEth, + }}, gasLimit) + simulatedBackend.Commit() + + CapabilitiesRegistryAddress, _, CapabilitiesRegistry, err := kcr.DeployCapabilitiesRegistry(owner, simulatedBackend) + require.NoError(t, err, "DeployCapabilitiesRegistry failed") + + fmt.Println("Deployed CapabilitiesRegistry at", CapabilitiesRegistryAddress.Hex()) + simulatedBackend.Commit() + + return CapabilitiesRegistry, CapabilitiesRegistryAddress, owner, simulatedBackend +} + +type crFactory struct { + lggr logger.Logger + logPoller logpoller.LogPoller + client evmclient.Client +} + +func (c *crFactory) NewContractReader(ctx context.Context, cfg []byte) (types.ContractReader, error) { + crCfg := &evmrelaytypes.ChainReaderConfig{} + if err := json.Unmarshal(cfg, crCfg); err != nil { + return nil, err + } + svc, err := evm.NewChainReaderService(ctx, c.lggr, c.logPoller, c.client, *crCfg) + if err != nil { + return nil, err + } + + return svc, svc.Start(ctx) +} + +func newContractReaderFactory(t *testing.T, simulatedBackend *backends.SimulatedBackend) *crFactory { + lggr := logger.TestLogger(t) + client := evmclient.NewSimulatedBackendClient( + t, + simulatedBackend, + testutils.SimulatedChainID, + ) + db := pgtest.NewSqlxDB(t) + lp := logpoller.NewLogPoller( + logpoller.NewORM(testutils.SimulatedChainID, db, lggr), + client, + lggr, + logpoller.Opts{ + PollPeriod: 100 * time.Millisecond, + FinalityDepth: 2, + BackfillBatchSize: 3, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 1000, + }, + ) + return &crFactory{ + lggr: lggr, + client: client, + logPoller: lp, + } +} + +func randomWord() [32]byte { + word := make([]byte, 32) + _, err := rand.Read(word) + if err != nil { + panic(err) + } + return [32]byte(word) +} + +type mockWrapper struct { + services.Service + peer p2ptypes.Peer +} + +func (m mockWrapper) GetPeer() p2ptypes.Peer { + return m.peer +} + +type mockPeer struct { + p2ptypes.Peer + peerID p2ptypes.PeerID +} + +func (m mockPeer) ID() p2ptypes.PeerID { + return m.peerID +} + +func TestReader_Integration(t *testing.T) { + ctx := testutils.Context(t) + reg, regAddress, owner, sim := startNewChainWithRegistry(t) + + _, err := reg.AddCapabilities(owner, []kcr.CapabilitiesRegistryCapability{writeChainCapability}) + require.NoError(t, err, "AddCapability failed for %s", writeChainCapability.LabelledName) + sim.Commit() + + cid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChainCapability.LabelledName, writeChainCapability.Version) + require.NoError(t, err) + + _, err = reg.AddNodeOperators(owner, []kcr.CapabilitiesRegistryNodeOperator{ + { + Admin: owner.From, + Name: "TEST_NOP", + }, + }) + require.NoError(t, err) + + nodeSet := [][32]byte{ + randomWord(), + randomWord(), + randomWord(), + } + + signersSet := [][32]byte{ + randomWord(), + randomWord(), + randomWord(), + } + + nodes := []kcr.CapabilitiesRegistryNodeParams{ + { + // The first NodeOperatorId has id 1 since the id is auto-incrementing. + NodeOperatorId: uint32(1), + Signer: signersSet[0], + P2pId: nodeSet[0], + HashedCapabilityIds: [][32]byte{cid}, + }, + { + // The first NodeOperatorId has id 1 since the id is auto-incrementing. + NodeOperatorId: uint32(1), + Signer: signersSet[1], + P2pId: nodeSet[1], + HashedCapabilityIds: [][32]byte{cid}, + }, + { + // The first NodeOperatorId has id 1 since the id is auto-incrementing. + NodeOperatorId: uint32(1), + Signer: signersSet[2], + P2pId: nodeSet[2], + HashedCapabilityIds: [][32]byte{cid}, + }, + } + _, err = reg.AddNodes(owner, nodes) + require.NoError(t, err) + + cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: cid, + Config: []byte(`{"hello": "world"}`), + }, + } + _, err = reg.AddDON( + owner, + nodeSet, + cfgs, + true, + true, + 1, + ) + sim.Commit() + + require.NoError(t, err) + + factory := newContractReaderFactory(t, sim) + pw := mockWrapper{ + peer: mockPeer{ + peerID: nodeSet[0], + }, + } + reader, err := newRemoteRegistryReader(ctx, logger.TestLogger(t), pw, factory, regAddress.Hex()) + require.NoError(t, err) + + s, err := reader.state(ctx) + require.NoError(t, err) + assert.Len(t, s.IDsToCapabilities, 1) + + gotCap := s.IDsToCapabilities[cid] + assert.Equal(t, kcr.CapabilitiesRegistryCapabilityInfo{ + HashedId: cid, + LabelledName: "write-chain", + Version: "1.0.1", + ResponseType: uint8(1), + CapabilityType: uint8(0), + IsDeprecated: false, + }, gotCap) + + assert.Len(t, s.IDsToDONs, 1) + assert.Equal(t, kcr.CapabilitiesRegistryDONInfo{ + Id: 1, // initial Id + ConfigCount: 1, // initial Count + IsPublic: true, + AcceptsWorkflows: true, + F: 1, + NodeP2PIds: nodeSet, + CapabilityConfigurations: cfgs, + }, s.IDsToDONs[1]) + + nodesInfo := []kcr.CapabilitiesRegistryNodeInfo{ + { + // The first NodeOperatorId has id 1 since the id is auto-incrementing. + NodeOperatorId: uint32(1), + ConfigCount: 1, + WorkflowDONId: 1, + Signer: signersSet[0], + P2pId: nodeSet[0], + HashedCapabilityIds: [][32]byte{cid}, + CapabilitiesDONIds: []*big.Int{}, + }, + { + // The first NodeOperatorId has id 1 since the id is auto-incrementing. + NodeOperatorId: uint32(1), + ConfigCount: 1, + WorkflowDONId: 1, + Signer: signersSet[1], + P2pId: nodeSet[1], + HashedCapabilityIds: [][32]byte{cid}, + CapabilitiesDONIds: []*big.Int{}, + }, + { + // The first NodeOperatorId has id 1 since the id is auto-incrementing. + NodeOperatorId: uint32(1), + ConfigCount: 1, + WorkflowDONId: 1, + Signer: signersSet[2], + P2pId: nodeSet[2], + HashedCapabilityIds: [][32]byte{cid}, + CapabilitiesDONIds: []*big.Int{}, + }, + } + + assert.Len(t, s.IDsToNodes, 3) + assert.Equal(t, map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + nodeSet[0]: nodesInfo[0], + nodeSet[1]: nodesInfo[1], + nodeSet[2]: nodesInfo[2], + }, s.IDsToNodes) + + node, err := reader.LocalNode(ctx) + require.NoError(t, err) + + assert.Equal(t, p2ptypes.PeerID(nodeSet[0]), *node.PeerID) + assert.Equal(t, fmt.Sprint(1), node.WorkflowDON.ID) +} diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 84174e0232..3cfe1d169b 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -2,6 +2,7 @@ package capabilities import ( "context" + "errors" "fmt" "sync" @@ -9,6 +10,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ) +var ( + ErrCapabilityAlreadyExists = errors.New("capability already exists") +) + // Registry is a struct for the registry of capabilities. // Registry is safe for concurrent use. type Registry struct { @@ -141,7 +146,7 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error id := info.ID _, ok := r.m[id] if ok { - return fmt.Errorf("capability with id: %s already exists", id) + return fmt.Errorf("%w: id %s found in registry", ErrCapabilityAlreadyExists, id) } r.m[id] = c @@ -153,6 +158,6 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error func NewRegistry(lggr logger.Logger) *Registry { return &Registry{ m: map[string]capabilities.BaseCapability{}, - lggr: lggr.Named("CapabilityRegistry"), + lggr: lggr.Named("CapabilitiesRegistry"), } } diff --git a/core/capabilities/registry_test.go b/core/capabilities/registry_test.go index 5208781700..77e5d9edcd 100644 --- a/core/capabilities/registry_test.go +++ b/core/capabilities/registry_test.go @@ -2,6 +2,7 @@ package capabilities_test import ( "context" + "errors" "fmt" "testing" @@ -85,7 +86,7 @@ func TestRegistry_NoDuplicateIDs(t *testing.T) { c2 := &mockCapability{CapabilityInfo: ci} err = r.Add(ctx, c2) - assert.ErrorContains(t, err, "capability with id: capability-1@1.0.0 already exists") + assert.True(t, errors.Is(err, coreCapabilities.ErrCapabilityAlreadyExists)) } func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { diff --git a/core/capabilities/remote/dispatcher.go b/core/capabilities/remote/dispatcher.go index 63b0fad7e9..b91211b5bf 100644 --- a/core/capabilities/remote/dispatcher.go +++ b/core/capabilities/remote/dispatcher.go @@ -6,6 +6,8 @@ import ( sync "sync" "time" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" "google.golang.org/protobuf/proto" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -24,7 +26,7 @@ type dispatcher struct { peerID p2ptypes.PeerID signer p2ptypes.Signer registry core.CapabilitiesRegistry - receivers map[key]remotetypes.Receiver + receivers map[key]*receiver mu sync.RWMutex stopCh services.StopChan wg sync.WaitGroup @@ -45,7 +47,7 @@ func NewDispatcher(peerWrapper p2ptypes.PeerWrapper, signer p2ptypes.Signer, reg peerWrapper: peerWrapper, signer: signer, registry: registry, - receivers: make(map[key]remotetypes.Receiver), + receivers: make(map[key]*receiver), stopCh: make(services.StopChan), lggr: lggr.Named("Dispatcher"), } @@ -58,12 +60,35 @@ func (d *dispatcher) Start(ctx context.Context) error { return fmt.Errorf("peer is not initialized") } d.wg.Add(1) - go d.receive() + go func() { + defer d.wg.Done() + d.receive() + }() + d.lggr.Info("dispatcher started") return nil } -func (d *dispatcher) SetReceiver(capabilityId string, donId string, receiver remotetypes.Receiver) error { +func (d *dispatcher) Close() error { + close(d.stopCh) + d.wg.Wait() + d.lggr.Info("dispatcher closed") + return nil +} + +var capReceiveChannelUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "capability_receive_channel_usage", + Help: "The usage of the receive channel for each capability, 0 indicates empty, 1 indicates full.", +}, []string{"capabilityId", "donId"}) + +const receiverBufferSize = 10000 + +type receiver struct { + cancel context.CancelFunc + ch chan *remotetypes.MessageBody +} + +func (d *dispatcher) SetReceiver(capabilityId string, donId string, rec remotetypes.Receiver) error { d.mu.Lock() defer d.mu.Unlock() k := key{capabilityId, donId} @@ -71,7 +96,29 @@ func (d *dispatcher) SetReceiver(capabilityId string, donId string, receiver rem if ok { return fmt.Errorf("receiver already exists for capability %s and don %s", capabilityId, donId) } - d.receivers[k] = receiver + + receiverCh := make(chan *remotetypes.MessageBody, receiverBufferSize) + + ctx, cancelCtx := d.stopCh.NewCtx() + d.wg.Add(1) + go func() { + defer cancelCtx() + defer d.wg.Done() + for { + select { + case <-ctx.Done(): + return + case msg := <-receiverCh: + rec.Receive(ctx, msg) + } + } + }() + + d.receivers[k] = &receiver{ + cancel: cancelCtx, + ch: receiverCh, + } + d.lggr.Debugw("receiver set", "capabilityId", capabilityId, "donId", donId) return nil } @@ -79,8 +126,13 @@ func (d *dispatcher) SetReceiver(capabilityId string, donId string, receiver rem func (d *dispatcher) RemoveReceiver(capabilityId string, donId string) { d.mu.Lock() defer d.mu.Unlock() - delete(d.receivers, key{capabilityId, donId}) - d.lggr.Debugw("receiver removed", "capabilityId", capabilityId, "donId", donId) + + receiverKey := key{capabilityId, donId} + if receiver, ok := d.receivers[receiverKey]; ok { + receiver.cancel() + delete(d.receivers, receiverKey) + d.lggr.Debugw("receiver removed", "capabilityId", capabilityId, "donId", donId) + } } func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBody) error { @@ -105,7 +157,6 @@ func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBo } func (d *dispatcher) receive() { - defer d.wg.Done() recvCh := d.peer.Receive() for { select { @@ -128,7 +179,14 @@ func (d *dispatcher) receive() { d.tryRespondWithError(msg.Sender, body, types.Error_CAPABILITY_NOT_FOUND) continue } - receiver.Receive(body) + + receiverQueueUsage := float64(len(receiver.ch)) / receiverBufferSize + capReceiveChannelUsage.WithLabelValues(k.capId, k.donId).Set(receiverQueueUsage) + select { + case receiver.ch <- body: + default: + d.lggr.Warnw("receiver channel full, dropping message", "capabilityId", k.capId, "donId", k.donId) + } } } } @@ -150,13 +208,6 @@ func (d *dispatcher) tryRespondWithError(peerID p2ptypes.PeerID, body *remotetyp } } -func (d *dispatcher) Close() error { - close(d.stopCh) - d.wg.Wait() - d.lggr.Info("dispatcher closed") - return nil -} - func (d *dispatcher) Ready() error { return nil } diff --git a/core/capabilities/remote/dispatcher_test.go b/core/capabilities/remote/dispatcher_test.go index b6ba31aa8f..040ee849e0 100644 --- a/core/capabilities/remote/dispatcher_test.go +++ b/core/capabilities/remote/dispatcher_test.go @@ -1,6 +1,7 @@ package remote_test import ( + "context" "errors" "testing" @@ -26,7 +27,7 @@ func newReceiver() *testReceiver { } } -func (r *testReceiver) Receive(msg *remotetypes.MessageBody) { +func (r *testReceiver) Receive(_ context.Context, msg *remotetypes.MessageBody) { r.ch <- msg } diff --git a/core/capabilities/remote/target/client.go b/core/capabilities/remote/target/client.go index 2fb1193016..dbb7c2f8bd 100644 --- a/core/capabilities/remote/target/client.go +++ b/core/capabilities/remote/target/client.go @@ -52,35 +52,14 @@ func NewClient(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commo } } -func (c *client) expireRequests() { - c.mutex.Lock() - defer c.mutex.Unlock() - - for messageID, req := range c.messageIDToCallerRequest { - if req.Expired() { - req.Cancel(errors.New("request expired")) - delete(c.messageIDToCallerRequest, messageID) - } - } -} - func (c *client) Start(ctx context.Context) error { return c.StartOnce(c.Name(), func() error { c.wg.Add(1) go func() { defer c.wg.Done() - ticker := time.NewTicker(c.requestTimeout) - defer ticker.Stop() - c.lggr.Info("TargetClient started") - for { - select { - case <-c.stopCh: - return - case <-ticker.C: - c.expireRequests() - } - } + c.checkForExpiredRequests() }() + c.lggr.Info("TargetClient started") return nil }) } @@ -88,12 +67,46 @@ func (c *client) Start(ctx context.Context) error { func (c *client) Close() error { return c.StopOnce(c.Name(), func() error { close(c.stopCh) + c.cancelAllRequests(errors.New("client closed")) c.wg.Wait() c.lggr.Info("TargetClient closed") return nil }) } +func (c *client) checkForExpiredRequests() { + ticker := time.NewTicker(c.requestTimeout) + defer ticker.Stop() + for { + select { + case <-c.stopCh: + return + case <-ticker.C: + c.expireRequests() + } + } +} + +func (c *client) expireRequests() { + c.mutex.Lock() + defer c.mutex.Unlock() + + for messageID, req := range c.messageIDToCallerRequest { + if req.Expired() { + req.Cancel(errors.New("request expired")) + delete(c.messageIDToCallerRequest, messageID) + } + } +} + +func (c *client) cancelAllRequests(err error) { + c.mutex.Lock() + defer c.mutex.Unlock() + for _, req := range c.messageIDToCallerRequest { + req.Cancel(err) + } +} + func (c *client) Info(ctx context.Context) (commoncap.CapabilityInfo, error) { return c.remoteCapabilityInfo, nil } @@ -121,8 +134,7 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest return nil, fmt.Errorf("request for message ID %s already exists", messageID) } - cCtx, _ := c.stopCh.NewCtx() - req, err := request.NewClientRequest(cCtx, c.lggr, capReq, messageID, c.remoteCapabilityInfo, c.localDONInfo, c.dispatcher, + req, err := request.NewClientRequest(ctx, c.lggr, capReq, messageID, c.remoteCapabilityInfo, c.localDONInfo, c.dispatcher, c.requestTimeout) if err != nil { return nil, fmt.Errorf("failed to create client request: %w", err) @@ -133,10 +145,9 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest return req.ResponseChan(), nil } -func (c *client) Receive(msg *types.MessageBody) { +func (c *client) Receive(ctx context.Context, msg *types.MessageBody) { c.mutex.Lock() defer c.mutex.Unlock() - ctx, _ := c.stopCh.NewCtx() messageID := GetMessageID(msg) @@ -146,11 +157,9 @@ func (c *client) Receive(msg *types.MessageBody) { return } - go func() { - if err := req.OnMessage(ctx, msg); err != nil { - c.lggr.Errorw("failed to add response to request", "messageID", messageID, "err", err) - } - }() + if err := req.OnMessage(ctx, msg); err != nil { + c.lggr.Errorw("failed to add response to request", "messageID", messageID, "err", err) + } } func GetMessageIDForRequest(req commoncap.CapabilityRequest) (string, error) { diff --git a/core/capabilities/remote/target/client_test.go b/core/capabilities/remote/target/client_test.go index 8665ffe754..64b824d74d 100644 --- a/core/capabilities/remote/target/client_test.go +++ b/core/capabilities/remote/target/client_test.go @@ -11,7 +11,7 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" - "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -22,8 +22,7 @@ import ( ) func Test_Client_DonTopologies(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) transmissionSchedule, err := values.NewMap(map[string]any{ "schedule": transmission.Schedule_OneAtATime, @@ -60,8 +59,7 @@ func Test_Client_DonTopologies(t *testing.T) { } func Test_Client_TransmissionSchedules(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -99,8 +97,7 @@ func Test_Client_TransmissionSchedules(t *testing.T) { } func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -155,7 +152,7 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo ID: "workflow-don", } - broker := newTestMessageBroker() + broker := newTestAsyncMessageBroker(t, 100) receivers := make([]remotetypes.Receiver, numCapabilityPeers) for i := 0; i < numCapabilityPeers; i++ { @@ -166,16 +163,17 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo } callers := make([]commoncap.TargetCapability, numWorkflowPeers) - srvcs := make([]services.Service, numWorkflowPeers) + for i := 0; i < numWorkflowPeers; i++ { workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeers[i]) caller := target.NewClient(capInfo, workflowDonInfo, workflowPeerDispatcher, workflowNodeResponseTimeout, lggr) - require.NoError(t, caller.Start(ctx)) + servicetest.Run(t, caller) broker.RegisterReceiverNode(workflowPeers[i], caller) callers[i] = caller - srvcs[i] = caller } + servicetest.Run(t, broker) + executeInputs, err := values.NewMap( map[string]any{ "executeValue1": "aValue1", @@ -190,6 +188,7 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo // Fire off all the requests for _, caller := range callers { go func(caller commoncap.TargetCapability) { + defer wg.Done() responseCh, err := caller.Execute(ctx, commoncap.CapabilityRequest{ Metadata: commoncap.RequestMetadata{ @@ -201,14 +200,10 @@ func testClient(ctx context.Context, t *testing.T, numWorkflowPeers int, workflo }) responseTest(t, responseCh, err) - wg.Done() }(caller) } wg.Wait() - for i := 0; i < numWorkflowPeers; i++ { - require.NoError(t, srvcs[i].Close()) - } } // Simple client that only responds once it has received a message from each workflow peer @@ -234,7 +229,7 @@ func newTestServer(peerID p2ptypes.PeerID, dispatcher remotetypes.Dispatcher, wo } } -func (t *clientTestServer) Receive(msg *remotetypes.MessageBody) { +func (t *clientTestServer) Receive(_ context.Context, msg *remotetypes.MessageBody) { t.mux.Lock() defer t.mux.Unlock() @@ -302,7 +297,7 @@ func NewTestDispatcher() *TestDispatcher { } func (t *TestDispatcher) SendToReceiver(msgBody *remotetypes.MessageBody) { - t.receiver.Receive(msgBody) + t.receiver.Receive(context.Background(), msgBody) } func (t *TestDispatcher) SetReceiver(capabilityId string, donId string, receiver remotetypes.Receiver) error { diff --git a/core/capabilities/remote/target/endtoend_test.go b/core/capabilities/remote/target/endtoend_test.go index a5379250e5..d5305afeb3 100644 --- a/core/capabilities/remote/target/endtoend_test.go +++ b/core/capabilities/remote/target/endtoend_test.go @@ -15,6 +15,8 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -25,8 +27,7 @@ import ( ) func Test_RemoteTargetCapability_InsufficientCapabilityResponses(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -46,8 +47,7 @@ func Test_RemoteTargetCapability_InsufficientCapabilityResponses(t *testing.T) { } func Test_RemoteTargetCapability_InsufficientWorkflowRequests(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -69,8 +69,7 @@ func Test_RemoteTargetCapability_InsufficientWorkflowRequests(t *testing.T) { } func Test_RemoteTargetCapability_TransmissionSchedules(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -102,8 +101,7 @@ func Test_RemoteTargetCapability_TransmissionSchedules(t *testing.T) { } func Test_RemoteTargetCapability_DonTopologies(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -138,8 +136,7 @@ func Test_RemoteTargetCapability_DonTopologies(t *testing.T) { } func Test_RemoteTargetCapability_CapabilityError(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -159,8 +156,7 @@ func Test_RemoteTargetCapability_CapabilityError(t *testing.T) { } func Test_RemoteTargetCapability_RandomCapabilityError(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) responseTest := func(t *testing.T, responseCh <-chan commoncap.CapabilityResponse, responseError error) { require.NoError(t, responseError) @@ -220,35 +216,34 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta F: workflowDonF, } - broker := newTestMessageBroker() + broker := newTestAsyncMessageBroker(t, 1000) workflowDONs := map[string]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } - srvcs := []services.Service{} capabilityNodes := make([]remotetypes.Receiver, numCapabilityPeers) for i := 0; i < numCapabilityPeers; i++ { capabilityPeer := capabilityPeers[i] capabilityDispatcher := broker.NewDispatcherForNode(capabilityPeer) capabilityNode := target.NewServer(capabilityPeer, underlying, capInfo, capDonInfo, workflowDONs, capabilityDispatcher, capabilityNodeResponseTimeout, lggr) - require.NoError(t, capabilityNode.Start(ctx)) + servicetest.Run(t, capabilityNode) broker.RegisterReceiverNode(capabilityPeer, capabilityNode) capabilityNodes[i] = capabilityNode - srvcs = append(srvcs, capabilityNode) } workflowNodes := make([]commoncap.TargetCapability, numWorkflowPeers) for i := 0; i < numWorkflowPeers; i++ { workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeers[i]) workflowNode := target.NewClient(capInfo, workflowDonInfo, workflowPeerDispatcher, workflowNodeTimeout, lggr) - require.NoError(t, workflowNode.Start(ctx)) + servicetest.Run(t, workflowNode) broker.RegisterReceiverNode(workflowPeers[i], workflowNode) workflowNodes[i] = workflowNode - srvcs = append(srvcs, workflowNode) } + servicetest.Run(t, broker) + executeInputs, err := values.NewMap( map[string]any{ "executeValue1": "aValue1", @@ -262,6 +257,7 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta for _, caller := range workflowNodes { go func(caller commoncap.TargetCapability) { + defer wg.Done() responseCh, err := caller.Execute(ctx, commoncap.CapabilityRequest{ Metadata: commoncap.RequestMetadata{ @@ -273,59 +269,106 @@ func testRemoteTarget(ctx context.Context, t *testing.T, underlying commoncap.Ta }) responseTest(t, responseCh, err) - wg.Done() }(caller) } wg.Wait() - for _, srv := range srvcs { - require.NoError(t, srv.Close()) - } } -type testMessageBroker struct { +type testAsyncMessageBroker struct { + services.StateMachine + t *testing.T + nodes map[p2ptypes.PeerID]remotetypes.Receiver + + sendCh chan *remotetypes.MessageBody + + stopCh services.StopChan + wg sync.WaitGroup } -func newTestMessageBroker() *testMessageBroker { - return &testMessageBroker{ - nodes: make(map[p2ptypes.PeerID]remotetypes.Receiver), +func (a *testAsyncMessageBroker) HealthReport() map[string]error { + return nil +} + +func (a *testAsyncMessageBroker) Name() string { + return "testAsyncMessageBroker" +} + +func newTestAsyncMessageBroker(t *testing.T, sendChBufferSize int) *testAsyncMessageBroker { + return &testAsyncMessageBroker{ + t: t, + nodes: make(map[p2ptypes.PeerID]remotetypes.Receiver), + stopCh: make(services.StopChan), + sendCh: make(chan *remotetypes.MessageBody, sendChBufferSize), } } -func (r *testMessageBroker) NewDispatcherForNode(nodePeerID p2ptypes.PeerID) remotetypes.Dispatcher { +func (a *testAsyncMessageBroker) Start(ctx context.Context) error { + return a.StartOnce("testAsyncMessageBroker", func() error { + a.wg.Add(1) + go func() { + defer a.wg.Done() + + for { + select { + case <-a.stopCh: + return + case msg := <-a.sendCh: + receiverId := toPeerID(msg.Receiver) + + receiver, ok := a.nodes[receiverId] + if !ok { + panic("server not found for peer id") + } + + receiver.Receive(tests.Context(a.t), msg) + } + } + }() + return nil + }) +} + +func (a *testAsyncMessageBroker) Close() error { + return a.StopOnce("testAsyncMessageBroker", func() error { + close(a.stopCh) + + a.wg.Wait() + return nil + }) +} + +func (a *testAsyncMessageBroker) NewDispatcherForNode(nodePeerID p2ptypes.PeerID) remotetypes.Dispatcher { return &nodeDispatcher{ callerPeerID: nodePeerID, - broker: r, + broker: a, } } -func (r *testMessageBroker) RegisterReceiverNode(nodePeerID p2ptypes.PeerID, node remotetypes.Receiver) { - if _, ok := r.nodes[nodePeerID]; ok { +func (a *testAsyncMessageBroker) RegisterReceiverNode(nodePeerID p2ptypes.PeerID, node remotetypes.Receiver) { + if _, ok := a.nodes[nodePeerID]; ok { panic("node already registered") } - r.nodes[nodePeerID] = node + a.nodes[nodePeerID] = node } -func (r *testMessageBroker) Send(msg *remotetypes.MessageBody) { - receiverId := toPeerID(msg.Receiver) - - receiver, ok := r.nodes[receiverId] - if !ok { - panic("server not found for peer id") - } - - receiver.Receive(msg) +func (a *testAsyncMessageBroker) Send(msg *remotetypes.MessageBody) { + a.sendCh <- msg } func toPeerID(id []byte) p2ptypes.PeerID { return [32]byte(id) } +type broker interface { + Send(msg *remotetypes.MessageBody) +} + type nodeDispatcher struct { callerPeerID p2ptypes.PeerID - broker *testMessageBroker + broker broker } func (t *nodeDispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBody) error { diff --git a/core/capabilities/remote/target/request/client_request.go b/core/capabilities/remote/target/request/client_request.go index 5f49040e0f..b48aa28207 100644 --- a/core/capabilities/remote/target/request/client_request.go +++ b/core/capabilities/remote/target/request/client_request.go @@ -21,6 +21,7 @@ import ( ) type ClientRequest struct { + cancelFn context.CancelFunc responseCh chan commoncap.CapabilityResponse createdAt time.Time responseIDCount map[[32]byte]int @@ -33,6 +34,7 @@ type ClientRequest struct { respSent bool mux sync.Mutex + wg *sync.WaitGroup } func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.CapabilityRequest, messageID string, @@ -48,13 +50,7 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap return nil, fmt.Errorf("failed to marshal capability request: %w", err) } - tc, err := transmission.ExtractTransmissionConfig(req.Config) - if err != nil { - return nil, fmt.Errorf("failed to extract transmission config from request config: %w", err) - } - - peerIDToTransmissionDelay, err := transmission.GetPeerIDToTransmissionDelay(remoteCapabilityDonInfo.Members, localDonInfo.Config.SharedSecret, - messageID, tc) + peerIDToTransmissionDelay, err := transmission.GetPeerIDToTransmissionDelay(remoteCapabilityDonInfo.Members, req) if err != nil { return nil, fmt.Errorf("failed to get peer ID to transmission delay: %w", err) } @@ -62,9 +58,14 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap lggr.Debugw("sending request to peers", "execID", req.Metadata.WorkflowExecutionID, "schedule", peerIDToTransmissionDelay) responseReceived := make(map[p2ptypes.PeerID]bool) + + ctxWithCancel, cancelFn := context.WithCancel(ctx) + wg := &sync.WaitGroup{} for peerID, delay := range peerIDToTransmissionDelay { responseReceived[peerID] = false - go func(peerID ragep2ptypes.PeerID, delay time.Duration) { + wg.Add(1) + go func(ctx context.Context, peerID ragep2ptypes.PeerID, delay time.Duration) { + defer wg.Done() message := &types.MessageBody{ CapabilityId: remoteCapabilityInfo.ID, CapabilityDonId: remoteCapabilityDonInfo.ID, @@ -75,7 +76,7 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap } select { - case <-ctx.Done(): + case <-ctxWithCancel.Done(): lggr.Debugw("context done, not sending request to peer", "execID", req.Metadata.WorkflowExecutionID, "peerID", peerID) return case <-time.After(delay): @@ -85,10 +86,11 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap lggr.Errorw("failed to send message", "peerID", peerID, "err", err) } } - }(peerID, delay) + }(ctxWithCancel, peerID, delay) } return &ClientRequest{ + cancelFn: cancelFn, createdAt: time.Now(), requestTimeout: requestTimeout, requiredIdenticalResponses: int(remoteCapabilityDonInfo.F + 1), @@ -96,6 +98,7 @@ func NewClientRequest(ctx context.Context, lggr logger.Logger, req commoncap.Cap errorCount: make(map[string]int), responseReceived: responseReceived, responseCh: make(chan commoncap.CapabilityResponse, 1), + wg: wg, }, nil } @@ -108,6 +111,8 @@ func (c *ClientRequest) Expired() bool { } func (c *ClientRequest) Cancel(err error) { + c.cancelFn() + c.wg.Wait() c.mux.Lock() defer c.mux.Unlock() if !c.respSent { diff --git a/core/capabilities/remote/target/request/client_request_test.go b/core/capabilities/remote/target/request/client_request_test.go index e4b0d9da88..a053623cd2 100644 --- a/core/capabilities/remote/target/request/client_request_test.go +++ b/core/capabilities/remote/target/request/client_request_test.go @@ -2,6 +2,7 @@ package request_test import ( "context" + "errors" "testing" "time" @@ -101,6 +102,8 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} request, err := request.NewClientRequest(ctx, lggr, capabilityRequest, messageID, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) + defer request.Cancel(errors.New("test end")) + require.NoError(t, err) capabilityResponse2 := commoncap.CapabilityResponse{ @@ -142,6 +145,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { request, err := request.NewClientRequest(ctx, lggr, capabilityRequest, messageID, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) require.NoError(t, err) + defer request.Cancel(errors.New("test end")) msg.Sender = capabilityPeers[0][:] err = request.OnMessage(ctx, msg) @@ -167,6 +171,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { request, err := request.NewClientRequest(ctx, lggr, capabilityRequest, messageID, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) require.NoError(t, err) + defer request.Cancel(errors.New("test end")) msg.Sender = capabilityPeers[0][:] err = request.OnMessage(ctx, msg) @@ -189,6 +194,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { request, err := request.NewClientRequest(ctx, lggr, capabilityRequest, messageID, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) require.NoError(t, err) + defer request.Cancel(errors.New("test end")) <-dispatcher.msgs <-dispatcher.msgs @@ -226,6 +232,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { request, err := request.NewClientRequest(ctx, lggr, capabilityRequest, messageID, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) require.NoError(t, err) + defer request.Cancel(errors.New("test end")) <-dispatcher.msgs <-dispatcher.msgs @@ -275,6 +282,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { request, err := request.NewClientRequest(ctx, lggr, capabilityRequest, messageID, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) require.NoError(t, err) + defer request.Cancel(errors.New("test end")) <-dispatcher.msgs <-dispatcher.msgs diff --git a/core/capabilities/remote/target/server.go b/core/capabilities/remote/target/server.go index 8ccbecf530..a918dd9170 100644 --- a/core/capabilities/remote/target/server.go +++ b/core/capabilities/remote/target/server.go @@ -106,12 +106,9 @@ func (r *server) expireRequests() { } } -// Receive handles incoming messages from remote nodes and dispatches them to the corresponding request without blocking -// the client. -func (r *server) Receive(msg *types.MessageBody) { +func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { r.receiveLock.Lock() defer r.receiveLock.Unlock() - ctx, _ := r.stopCh.NewCtx() if msg.Method != types.MethodExecute { r.lggr.Errorw("received request for unsupported method type", "method", msg.Method) @@ -137,12 +134,10 @@ func (r *server) Receive(msg *types.MessageBody) { req := r.requestIDToRequest[requestID] - go func() { - err := req.OnMessage(ctx, msg) - if err != nil { - r.lggr.Errorw("request failed to OnMessage new message", "request", req, "err", err) - } - }() + err := req.OnMessage(ctx, msg) + if err != nil { + r.lggr.Errorw("request failed to OnMessage new message", "request", req, "err", err) + } } func GetMessageID(msg *types.MessageBody) string { diff --git a/core/capabilities/remote/target/server_test.go b/core/capabilities/remote/target/server_test.go index e6d85ebff2..3c12ce813d 100644 --- a/core/capabilities/remote/target/server_test.go +++ b/core/capabilities/remote/target/server_test.go @@ -19,8 +19,7 @@ import ( ) func Test_Server_RespondsAfterSufficientRequests(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) numCapabilityPeers := 4 @@ -47,8 +46,7 @@ func Test_Server_RespondsAfterSufficientRequests(t *testing.T) { } func Test_Server_InsufficientCallers(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) numCapabilityPeers := 4 @@ -75,8 +73,7 @@ func Test_Server_InsufficientCallers(t *testing.T) { } func Test_Server_CapabilityError(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) numCapabilityPeers := 4 @@ -138,14 +135,18 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, F: workflowDonF, } - broker := newTestMessageBroker() + var srvcs []services.Service + broker := newTestAsyncMessageBroker(t, 1000) + err := broker.Start(context.Background()) + require.NoError(t, err) + srvcs = append(srvcs, broker) workflowDONs := map[string]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, } capabilityNodes := make([]remotetypes.Receiver, numCapabilityPeers) - srvcs := make([]services.Service, numCapabilityPeers) + for i := 0; i < numCapabilityPeers; i++ { capabilityPeer := capabilityPeers[i] capabilityDispatcher := broker.NewDispatcherForNode(capabilityPeer) @@ -154,7 +155,7 @@ func testRemoteTargetServer(ctx context.Context, t *testing.T, require.NoError(t, capabilityNode.Start(ctx)) broker.RegisterReceiverNode(capabilityPeer, capabilityNode) capabilityNodes[i] = capabilityNode - srvcs[i] = capabilityNode + srvcs = append(srvcs, capabilityNode) } workflowNodes := make([]*serverTestClient, numWorkflowPeers) @@ -182,7 +183,7 @@ type serverTestClient struct { callerDonID string } -func (r *serverTestClient) Receive(msg *remotetypes.MessageBody) { +func (r *serverTestClient) Receive(_ context.Context, msg *remotetypes.MessageBody) { r.receivedMessages <- msg } diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 12d539a2dc..9e7fc89352 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -21,7 +21,7 @@ import ( // // TriggerPublisher communicates with corresponding TriggerSubscribers on remote nodes. type triggerPublisher struct { - config types.RemoteTriggerConfig + config *types.RemoteTriggerConfig underlying commoncap.TriggerCapability capInfo commoncap.CapabilityInfo capDonInfo commoncap.DON @@ -48,7 +48,7 @@ type pubRegState struct { var _ types.Receiver = &triggerPublisher{} var _ services.Service = &triggerPublisher{} -func NewTriggerPublisher(config types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { +func NewTriggerPublisher(config *types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[string]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { config.ApplyDefaults() return &triggerPublisher{ config: config, @@ -71,7 +71,7 @@ func (p *triggerPublisher) Start(ctx context.Context) error { return nil } -func (p *triggerPublisher) Receive(msg *types.MessageBody) { +func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { sender := ToPeerID(msg.Sender) if msg.Method == types.MethodRegisterTrigger { req, err := pb.UnmarshalCapabilityRequest(msg.Payload) diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index 15bdd39b55..db792fb506 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -40,7 +40,7 @@ func TestTriggerPublisher_Register(t *testing.T) { } dispatcher := remoteMocks.NewDispatcher(t) - config := remotetypes.RemoteTriggerConfig{ + config := &remotetypes.RemoteTriggerConfig{ RegistrationRefreshMs: 100, RegistrationExpiryMs: 100_000, MinResponsesToAggregate: 1, @@ -70,7 +70,7 @@ func TestTriggerPublisher_Register(t *testing.T) { CallerDonId: workflowDonInfo.ID, Payload: marshaled, } - publisher.Receive(regEvent) + publisher.Receive(ctx, regEvent) forwarded := <-underlying.registrationsCh require.Equal(t, capRequest.Metadata.WorkflowID, forwarded.Metadata.WorkflowID) diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index b8c3d37a59..b20adc3697 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -23,7 +23,7 @@ import ( // // TriggerSubscriber communicates with corresponding TriggerReceivers on remote nodes. type triggerSubscriber struct { - config types.RemoteTriggerConfig + config *types.RemoteTriggerConfig capInfo commoncap.CapabilityInfo capDonInfo capabilities.DON capDonMembers map[p2ptypes.PeerID]struct{} @@ -55,7 +55,7 @@ var _ services.Service = &triggerSubscriber{} // TODO makes this configurable with a default const defaultSendChannelBufferSize = 1000 -func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo capabilities.DON, localDonInfo capabilities.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { +func NewTriggerSubscriber(config *types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo capabilities.DON, localDonInfo capabilities.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) @@ -168,7 +168,7 @@ func (s *triggerSubscriber) UnregisterTrigger(ctx context.Context, request commo return nil } -func (s *triggerSubscriber) Receive(msg *types.MessageBody) { +func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { sender := ToPeerID(msg.Sender) if _, found := s.capDonMembers[sender]; !found { s.lggr.Errorw("received message from unexpected node", "capabilityId", s.capInfo.ID, "sender", sender) diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index e50f570bb7..3b819f9f3c 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -58,7 +58,7 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { }) // register trigger - config := remotetypes.RemoteTriggerConfig{ + config := &remotetypes.RemoteTriggerConfig{ RegistrationRefreshMs: 100, RegistrationExpiryMs: 100, MinResponsesToAggregate: 1, @@ -95,7 +95,7 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { }, Payload: marshaled, } - subscriber.Receive(triggerEvent) + subscriber.Receive(ctx, triggerEvent) response := <-triggerEventCallbackCh require.Equal(t, response.Value, triggerEventValue) diff --git a/core/capabilities/remote/types/config.go b/core/capabilities/remote/types/config.go index 588ae98095..bb9e0fa434 100644 --- a/core/capabilities/remote/types/config.go +++ b/core/capabilities/remote/types/config.go @@ -8,13 +8,6 @@ const ( // NOTE: consider splitting this config into values stored in Registry (KS-118) // and values defined locally by Capability owners. -type RemoteTriggerConfig struct { - RegistrationRefreshMs uint32 - RegistrationExpiryMs uint32 - MinResponsesToAggregate uint32 - MessageExpiryMs uint32 -} - func (c *RemoteTriggerConfig) ApplyDefaults() { if c.RegistrationRefreshMs == 0 { c.RegistrationRefreshMs = DefaultRegistrationRefreshMs diff --git a/core/capabilities/remote/types/message.pb.go b/core/capabilities/remote/types/message.pb.go deleted file mode 100644 index 7cef9d4574..0000000000 --- a/core/capabilities/remote/types/message.pb.go +++ /dev/null @@ -1,597 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.1 -// source: core/capabilities/remote/types/message.proto - -package types - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Error int32 - -const ( - Error_OK Error = 0 - Error_VALIDATION_FAILED Error = 1 - Error_CAPABILITY_NOT_FOUND Error = 2 - Error_INVALID_REQUEST Error = 3 - Error_TIMEOUT Error = 4 - Error_INTERNAL_ERROR Error = 5 -) - -// Enum value maps for Error. -var ( - Error_name = map[int32]string{ - 0: "OK", - 1: "VALIDATION_FAILED", - 2: "CAPABILITY_NOT_FOUND", - 3: "INVALID_REQUEST", - 4: "TIMEOUT", - 5: "INTERNAL_ERROR", - } - Error_value = map[string]int32{ - "OK": 0, - "VALIDATION_FAILED": 1, - "CAPABILITY_NOT_FOUND": 2, - "INVALID_REQUEST": 3, - "TIMEOUT": 4, - "INTERNAL_ERROR": 5, - } -) - -func (x Error) Enum() *Error { - p := new(Error) - *p = x - return p -} - -func (x Error) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Error) Descriptor() protoreflect.EnumDescriptor { - return file_core_capabilities_remote_types_message_proto_enumTypes[0].Descriptor() -} - -func (Error) Type() protoreflect.EnumType { - return &file_core_capabilities_remote_types_message_proto_enumTypes[0] -} - -func (x Error) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Error.Descriptor instead. -func (Error) EnumDescriptor() ([]byte, []int) { - return file_core_capabilities_remote_types_message_proto_rawDescGZIP(), []int{0} -} - -type Message struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` - Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` // proto-encoded MessageBody to sign -} - -func (x *Message) Reset() { - *x = Message{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Message) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Message) ProtoMessage() {} - -func (x *Message) ProtoReflect() protoreflect.Message { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Message.ProtoReflect.Descriptor instead. -func (*Message) Descriptor() ([]byte, []int) { - return file_core_capabilities_remote_types_message_proto_rawDescGZIP(), []int{0} -} - -func (x *Message) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *Message) GetBody() []byte { - if x != nil { - return x.Body - } - return nil -} - -type MessageBody struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - Receiver []byte `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` - Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - MessageId []byte `protobuf:"bytes,5,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` // scoped to sender - CapabilityId string `protobuf:"bytes,6,opt,name=capability_id,json=capabilityId,proto3" json:"capability_id,omitempty"` - CapabilityDonId string `protobuf:"bytes,7,opt,name=capability_don_id,json=capabilityDonId,proto3" json:"capability_don_id,omitempty"` - CallerDonId string `protobuf:"bytes,8,opt,name=caller_don_id,json=callerDonId,proto3" json:"caller_don_id,omitempty"` - Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"` - Error Error `protobuf:"varint,10,opt,name=error,proto3,enum=remote.Error" json:"error,omitempty"` - ErrorMsg string `protobuf:"bytes,11,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"` - // payload contains a CapabilityRequest or CapabilityResponse - Payload []byte `protobuf:"bytes,12,opt,name=payload,proto3" json:"payload,omitempty"` - // Types that are assignable to Metadata: - // - // *MessageBody_TriggerRegistrationMetadata - // *MessageBody_TriggerEventMetadata - Metadata isMessageBody_Metadata `protobuf_oneof:"metadata"` -} - -func (x *MessageBody) Reset() { - *x = MessageBody{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MessageBody) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MessageBody) ProtoMessage() {} - -func (x *MessageBody) ProtoReflect() protoreflect.Message { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MessageBody.ProtoReflect.Descriptor instead. -func (*MessageBody) Descriptor() ([]byte, []int) { - return file_core_capabilities_remote_types_message_proto_rawDescGZIP(), []int{1} -} - -func (x *MessageBody) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 -} - -func (x *MessageBody) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *MessageBody) GetReceiver() []byte { - if x != nil { - return x.Receiver - } - return nil -} - -func (x *MessageBody) GetTimestamp() int64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *MessageBody) GetMessageId() []byte { - if x != nil { - return x.MessageId - } - return nil -} - -func (x *MessageBody) GetCapabilityId() string { - if x != nil { - return x.CapabilityId - } - return "" -} - -func (x *MessageBody) GetCapabilityDonId() string { - if x != nil { - return x.CapabilityDonId - } - return "" -} - -func (x *MessageBody) GetCallerDonId() string { - if x != nil { - return x.CallerDonId - } - return "" -} - -func (x *MessageBody) GetMethod() string { - if x != nil { - return x.Method - } - return "" -} - -func (x *MessageBody) GetError() Error { - if x != nil { - return x.Error - } - return Error_OK -} - -func (x *MessageBody) GetErrorMsg() string { - if x != nil { - return x.ErrorMsg - } - return "" -} - -func (x *MessageBody) GetPayload() []byte { - if x != nil { - return x.Payload - } - return nil -} - -func (m *MessageBody) GetMetadata() isMessageBody_Metadata { - if m != nil { - return m.Metadata - } - return nil -} - -func (x *MessageBody) GetTriggerRegistrationMetadata() *TriggerRegistrationMetadata { - if x, ok := x.GetMetadata().(*MessageBody_TriggerRegistrationMetadata); ok { - return x.TriggerRegistrationMetadata - } - return nil -} - -func (x *MessageBody) GetTriggerEventMetadata() *TriggerEventMetadata { - if x, ok := x.GetMetadata().(*MessageBody_TriggerEventMetadata); ok { - return x.TriggerEventMetadata - } - return nil -} - -type isMessageBody_Metadata interface { - isMessageBody_Metadata() -} - -type MessageBody_TriggerRegistrationMetadata struct { - TriggerRegistrationMetadata *TriggerRegistrationMetadata `protobuf:"bytes,13,opt,name=trigger_registration_metadata,json=triggerRegistrationMetadata,proto3,oneof"` -} - -type MessageBody_TriggerEventMetadata struct { - TriggerEventMetadata *TriggerEventMetadata `protobuf:"bytes,14,opt,name=trigger_event_metadata,json=triggerEventMetadata,proto3,oneof"` -} - -func (*MessageBody_TriggerRegistrationMetadata) isMessageBody_Metadata() {} - -func (*MessageBody_TriggerEventMetadata) isMessageBody_Metadata() {} - -type TriggerRegistrationMetadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - LastReceivedEventId string `protobuf:"bytes,1,opt,name=last_received_event_id,json=lastReceivedEventId,proto3" json:"last_received_event_id,omitempty"` -} - -func (x *TriggerRegistrationMetadata) Reset() { - *x = TriggerRegistrationMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TriggerRegistrationMetadata) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TriggerRegistrationMetadata) ProtoMessage() {} - -func (x *TriggerRegistrationMetadata) ProtoReflect() protoreflect.Message { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TriggerRegistrationMetadata.ProtoReflect.Descriptor instead. -func (*TriggerRegistrationMetadata) Descriptor() ([]byte, []int) { - return file_core_capabilities_remote_types_message_proto_rawDescGZIP(), []int{2} -} - -func (x *TriggerRegistrationMetadata) GetLastReceivedEventId() string { - if x != nil { - return x.LastReceivedEventId - } - return "" -} - -type TriggerEventMetadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TriggerEventId string `protobuf:"bytes,1,opt,name=trigger_event_id,json=triggerEventId,proto3" json:"trigger_event_id,omitempty"` - WorkflowIds []string `protobuf:"bytes,2,rep,name=workflow_ids,json=workflowIds,proto3" json:"workflow_ids,omitempty"` -} - -func (x *TriggerEventMetadata) Reset() { - *x = TriggerEventMetadata{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TriggerEventMetadata) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TriggerEventMetadata) ProtoMessage() {} - -func (x *TriggerEventMetadata) ProtoReflect() protoreflect.Message { - mi := &file_core_capabilities_remote_types_message_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TriggerEventMetadata.ProtoReflect.Descriptor instead. -func (*TriggerEventMetadata) Descriptor() ([]byte, []int) { - return file_core_capabilities_remote_types_message_proto_rawDescGZIP(), []int{3} -} - -func (x *TriggerEventMetadata) GetTriggerEventId() string { - if x != nil { - return x.TriggerEventId - } - return "" -} - -func (x *TriggerEventMetadata) GetWorkflowIds() []string { - if x != nil { - return x.WorkflowIds - } - return nil -} - -var File_core_capabilities_remote_types_message_proto protoreflect.FileDescriptor - -var file_core_capabilities_remote_types_message_proto_rawDesc = []byte{ - 0x0a, 0x2c, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x22, 0xcd, 0x04, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x23, - 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x44, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, 0x0a, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x69, 0x0a, 0x1d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x48, 0x00, 0x52, 0x1b, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x54, 0x0a, 0x16, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, - 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x48, - 0x00, 0x52, 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x22, 0x52, 0x0a, 0x1b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x33, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x63, 0x0a, 0x14, 0x54, 0x72, 0x69, 0x67, 0x67, - 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x28, 0x0a, 0x10, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x69, 0x67, 0x67, - 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x2a, 0x76, 0x0a, 0x05, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x15, 0x0a, - 0x11, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, - 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, - 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x13, - 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, - 0x54, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, - 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x05, 0x42, 0x20, 0x5a, 0x1e, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_core_capabilities_remote_types_message_proto_rawDescOnce sync.Once - file_core_capabilities_remote_types_message_proto_rawDescData = file_core_capabilities_remote_types_message_proto_rawDesc -) - -func file_core_capabilities_remote_types_message_proto_rawDescGZIP() []byte { - file_core_capabilities_remote_types_message_proto_rawDescOnce.Do(func() { - file_core_capabilities_remote_types_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_capabilities_remote_types_message_proto_rawDescData) - }) - return file_core_capabilities_remote_types_message_proto_rawDescData -} - -var file_core_capabilities_remote_types_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_core_capabilities_remote_types_message_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_core_capabilities_remote_types_message_proto_goTypes = []interface{}{ - (Error)(0), // 0: remote.Error - (*Message)(nil), // 1: remote.Message - (*MessageBody)(nil), // 2: remote.MessageBody - (*TriggerRegistrationMetadata)(nil), // 3: remote.TriggerRegistrationMetadata - (*TriggerEventMetadata)(nil), // 4: remote.TriggerEventMetadata -} -var file_core_capabilities_remote_types_message_proto_depIdxs = []int32{ - 0, // 0: remote.MessageBody.error:type_name -> remote.Error - 3, // 1: remote.MessageBody.trigger_registration_metadata:type_name -> remote.TriggerRegistrationMetadata - 4, // 2: remote.MessageBody.trigger_event_metadata:type_name -> remote.TriggerEventMetadata - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_core_capabilities_remote_types_message_proto_init() } -func file_core_capabilities_remote_types_message_proto_init() { - if File_core_capabilities_remote_types_message_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_core_capabilities_remote_types_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Message); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_capabilities_remote_types_message_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MessageBody); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_capabilities_remote_types_message_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TriggerRegistrationMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_core_capabilities_remote_types_message_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TriggerEventMetadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_core_capabilities_remote_types_message_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*MessageBody_TriggerRegistrationMetadata)(nil), - (*MessageBody_TriggerEventMetadata)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_core_capabilities_remote_types_message_proto_rawDesc, - NumEnums: 1, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_core_capabilities_remote_types_message_proto_goTypes, - DependencyIndexes: file_core_capabilities_remote_types_message_proto_depIdxs, - EnumInfos: file_core_capabilities_remote_types_message_proto_enumTypes, - MessageInfos: file_core_capabilities_remote_types_message_proto_msgTypes, - }.Build() - File_core_capabilities_remote_types_message_proto = out.File - file_core_capabilities_remote_types_message_proto_rawDesc = nil - file_core_capabilities_remote_types_message_proto_goTypes = nil - file_core_capabilities_remote_types_message_proto_depIdxs = nil -} diff --git a/core/capabilities/remote/types/messages.pb.go b/core/capabilities/remote/types/messages.pb.go new file mode 100644 index 0000000000..0e51b39599 --- /dev/null +++ b/core/capabilities/remote/types/messages.pb.go @@ -0,0 +1,696 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v4.25.1 +// source: core/capabilities/remote/types/messages.proto + +package types + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Error int32 + +const ( + Error_OK Error = 0 + Error_VALIDATION_FAILED Error = 1 + Error_CAPABILITY_NOT_FOUND Error = 2 + Error_INVALID_REQUEST Error = 3 + Error_TIMEOUT Error = 4 + Error_INTERNAL_ERROR Error = 5 +) + +// Enum value maps for Error. +var ( + Error_name = map[int32]string{ + 0: "OK", + 1: "VALIDATION_FAILED", + 2: "CAPABILITY_NOT_FOUND", + 3: "INVALID_REQUEST", + 4: "TIMEOUT", + 5: "INTERNAL_ERROR", + } + Error_value = map[string]int32{ + "OK": 0, + "VALIDATION_FAILED": 1, + "CAPABILITY_NOT_FOUND": 2, + "INVALID_REQUEST": 3, + "TIMEOUT": 4, + "INTERNAL_ERROR": 5, + } +) + +func (x Error) Enum() *Error { + p := new(Error) + *p = x + return p +} + +func (x Error) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Error) Descriptor() protoreflect.EnumDescriptor { + return file_core_capabilities_remote_types_messages_proto_enumTypes[0].Descriptor() +} + +func (Error) Type() protoreflect.EnumType { + return &file_core_capabilities_remote_types_messages_proto_enumTypes[0] +} + +func (x Error) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Error.Descriptor instead. +func (Error) EnumDescriptor() ([]byte, []int) { + return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{0} +} + +type Message struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` // proto-encoded MessageBody to sign +} + +func (x *Message) Reset() { + *x = Message{} + if protoimpl.UnsafeEnabled { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Message) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Message) ProtoMessage() {} + +func (x *Message) ProtoReflect() protoreflect.Message { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Message.ProtoReflect.Descriptor instead. +func (*Message) Descriptor() ([]byte, []int) { + return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{0} +} + +func (x *Message) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *Message) GetBody() []byte { + if x != nil { + return x.Body + } + return nil +} + +type MessageBody struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` + Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` + Receiver []byte `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` + Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + MessageId []byte `protobuf:"bytes,5,opt,name=message_id,json=messageId,proto3" json:"message_id,omitempty"` // scoped to sender + CapabilityId string `protobuf:"bytes,6,opt,name=capability_id,json=capabilityId,proto3" json:"capability_id,omitempty"` + CapabilityDonId string `protobuf:"bytes,7,opt,name=capability_don_id,json=capabilityDonId,proto3" json:"capability_don_id,omitempty"` + CallerDonId string `protobuf:"bytes,8,opt,name=caller_don_id,json=callerDonId,proto3" json:"caller_don_id,omitempty"` + Method string `protobuf:"bytes,9,opt,name=method,proto3" json:"method,omitempty"` + Error Error `protobuf:"varint,10,opt,name=error,proto3,enum=remote.Error" json:"error,omitempty"` + ErrorMsg string `protobuf:"bytes,11,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"` + // payload contains a CapabilityRequest or CapabilityResponse + Payload []byte `protobuf:"bytes,12,opt,name=payload,proto3" json:"payload,omitempty"` + // Types that are assignable to Metadata: + // + // *MessageBody_TriggerRegistrationMetadata + // *MessageBody_TriggerEventMetadata + Metadata isMessageBody_Metadata `protobuf_oneof:"metadata"` +} + +func (x *MessageBody) Reset() { + *x = MessageBody{} + if protoimpl.UnsafeEnabled { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MessageBody) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MessageBody) ProtoMessage() {} + +func (x *MessageBody) ProtoReflect() protoreflect.Message { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MessageBody.ProtoReflect.Descriptor instead. +func (*MessageBody) Descriptor() ([]byte, []int) { + return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{1} +} + +func (x *MessageBody) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *MessageBody) GetSender() []byte { + if x != nil { + return x.Sender + } + return nil +} + +func (x *MessageBody) GetReceiver() []byte { + if x != nil { + return x.Receiver + } + return nil +} + +func (x *MessageBody) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *MessageBody) GetMessageId() []byte { + if x != nil { + return x.MessageId + } + return nil +} + +func (x *MessageBody) GetCapabilityId() string { + if x != nil { + return x.CapabilityId + } + return "" +} + +func (x *MessageBody) GetCapabilityDonId() string { + if x != nil { + return x.CapabilityDonId + } + return "" +} + +func (x *MessageBody) GetCallerDonId() string { + if x != nil { + return x.CallerDonId + } + return "" +} + +func (x *MessageBody) GetMethod() string { + if x != nil { + return x.Method + } + return "" +} + +func (x *MessageBody) GetError() Error { + if x != nil { + return x.Error + } + return Error_OK +} + +func (x *MessageBody) GetErrorMsg() string { + if x != nil { + return x.ErrorMsg + } + return "" +} + +func (x *MessageBody) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +func (m *MessageBody) GetMetadata() isMessageBody_Metadata { + if m != nil { + return m.Metadata + } + return nil +} + +func (x *MessageBody) GetTriggerRegistrationMetadata() *TriggerRegistrationMetadata { + if x, ok := x.GetMetadata().(*MessageBody_TriggerRegistrationMetadata); ok { + return x.TriggerRegistrationMetadata + } + return nil +} + +func (x *MessageBody) GetTriggerEventMetadata() *TriggerEventMetadata { + if x, ok := x.GetMetadata().(*MessageBody_TriggerEventMetadata); ok { + return x.TriggerEventMetadata + } + return nil +} + +type isMessageBody_Metadata interface { + isMessageBody_Metadata() +} + +type MessageBody_TriggerRegistrationMetadata struct { + TriggerRegistrationMetadata *TriggerRegistrationMetadata `protobuf:"bytes,13,opt,name=trigger_registration_metadata,json=triggerRegistrationMetadata,proto3,oneof"` +} + +type MessageBody_TriggerEventMetadata struct { + TriggerEventMetadata *TriggerEventMetadata `protobuf:"bytes,14,opt,name=trigger_event_metadata,json=triggerEventMetadata,proto3,oneof"` +} + +func (*MessageBody_TriggerRegistrationMetadata) isMessageBody_Metadata() {} + +func (*MessageBody_TriggerEventMetadata) isMessageBody_Metadata() {} + +type TriggerRegistrationMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LastReceivedEventId string `protobuf:"bytes,1,opt,name=last_received_event_id,json=lastReceivedEventId,proto3" json:"last_received_event_id,omitempty"` +} + +func (x *TriggerRegistrationMetadata) Reset() { + *x = TriggerRegistrationMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TriggerRegistrationMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TriggerRegistrationMetadata) ProtoMessage() {} + +func (x *TriggerRegistrationMetadata) ProtoReflect() protoreflect.Message { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TriggerRegistrationMetadata.ProtoReflect.Descriptor instead. +func (*TriggerRegistrationMetadata) Descriptor() ([]byte, []int) { + return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{2} +} + +func (x *TriggerRegistrationMetadata) GetLastReceivedEventId() string { + if x != nil { + return x.LastReceivedEventId + } + return "" +} + +type TriggerEventMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TriggerEventId string `protobuf:"bytes,1,opt,name=trigger_event_id,json=triggerEventId,proto3" json:"trigger_event_id,omitempty"` + WorkflowIds []string `protobuf:"bytes,2,rep,name=workflow_ids,json=workflowIds,proto3" json:"workflow_ids,omitempty"` +} + +func (x *TriggerEventMetadata) Reset() { + *x = TriggerEventMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TriggerEventMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TriggerEventMetadata) ProtoMessage() {} + +func (x *TriggerEventMetadata) ProtoReflect() protoreflect.Message { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TriggerEventMetadata.ProtoReflect.Descriptor instead. +func (*TriggerEventMetadata) Descriptor() ([]byte, []int) { + return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{3} +} + +func (x *TriggerEventMetadata) GetTriggerEventId() string { + if x != nil { + return x.TriggerEventId + } + return "" +} + +func (x *TriggerEventMetadata) GetWorkflowIds() []string { + if x != nil { + return x.WorkflowIds + } + return nil +} + +type RemoteTriggerConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RegistrationRefreshMs uint32 `protobuf:"varint,1,opt,name=registrationRefreshMs,proto3" json:"registrationRefreshMs,omitempty"` + RegistrationExpiryMs uint32 `protobuf:"varint,2,opt,name=registrationExpiryMs,proto3" json:"registrationExpiryMs,omitempty"` + MinResponsesToAggregate uint32 `protobuf:"varint,3,opt,name=minResponsesToAggregate,proto3" json:"minResponsesToAggregate,omitempty"` + MessageExpiryMs uint32 `protobuf:"varint,4,opt,name=messageExpiryMs,proto3" json:"messageExpiryMs,omitempty"` +} + +func (x *RemoteTriggerConfig) Reset() { + *x = RemoteTriggerConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoteTriggerConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoteTriggerConfig) ProtoMessage() {} + +func (x *RemoteTriggerConfig) ProtoReflect() protoreflect.Message { + mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoteTriggerConfig.ProtoReflect.Descriptor instead. +func (*RemoteTriggerConfig) Descriptor() ([]byte, []int) { + return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{4} +} + +func (x *RemoteTriggerConfig) GetRegistrationRefreshMs() uint32 { + if x != nil { + return x.RegistrationRefreshMs + } + return 0 +} + +func (x *RemoteTriggerConfig) GetRegistrationExpiryMs() uint32 { + if x != nil { + return x.RegistrationExpiryMs + } + return 0 +} + +func (x *RemoteTriggerConfig) GetMinResponsesToAggregate() uint32 { + if x != nil { + return x.MinResponsesToAggregate + } + return 0 +} + +func (x *RemoteTriggerConfig) GetMessageExpiryMs() uint32 { + if x != nil { + return x.MessageExpiryMs + } + return 0 +} + +var File_core_capabilities_remote_types_messages_proto protoreflect.FileDescriptor + +var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{ + 0x0a, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x22, 0xcd, 0x04, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x44, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x23, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0d, 0x2e, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x18, 0x0a, + 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x69, 0x0a, 0x1d, 0x74, 0x72, 0x69, 0x67, 0x67, + 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x1b, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x54, 0x0a, 0x16, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x48, 0x00, 0x52, 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x0a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x22, 0x52, 0x0a, 0x1b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x63, 0x0a, 0x14, 0x54, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x28, 0x0a, 0x10, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x22, 0xe3, 0x01, + 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, + 0x79, 0x4d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x73, 0x12, + 0x38, 0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x54, + 0x6f, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x17, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x54, 0x6f, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, + 0x79, 0x4d, 0x73, 0x2a, 0x76, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x06, 0x0a, 0x02, + 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, + 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, + 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, + 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, + 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x52, + 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x42, 0x20, 0x5a, 0x1e, 0x63, + 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_core_capabilities_remote_types_messages_proto_rawDescOnce sync.Once + file_core_capabilities_remote_types_messages_proto_rawDescData = file_core_capabilities_remote_types_messages_proto_rawDesc +) + +func file_core_capabilities_remote_types_messages_proto_rawDescGZIP() []byte { + file_core_capabilities_remote_types_messages_proto_rawDescOnce.Do(func() { + file_core_capabilities_remote_types_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_capabilities_remote_types_messages_proto_rawDescData) + }) + return file_core_capabilities_remote_types_messages_proto_rawDescData +} + +var file_core_capabilities_remote_types_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_core_capabilities_remote_types_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_core_capabilities_remote_types_messages_proto_goTypes = []interface{}{ + (Error)(0), // 0: remote.Error + (*Message)(nil), // 1: remote.Message + (*MessageBody)(nil), // 2: remote.MessageBody + (*TriggerRegistrationMetadata)(nil), // 3: remote.TriggerRegistrationMetadata + (*TriggerEventMetadata)(nil), // 4: remote.TriggerEventMetadata + (*RemoteTriggerConfig)(nil), // 5: remote.RemoteTriggerConfig +} +var file_core_capabilities_remote_types_messages_proto_depIdxs = []int32{ + 0, // 0: remote.MessageBody.error:type_name -> remote.Error + 3, // 1: remote.MessageBody.trigger_registration_metadata:type_name -> remote.TriggerRegistrationMetadata + 4, // 2: remote.MessageBody.trigger_event_metadata:type_name -> remote.TriggerEventMetadata + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_core_capabilities_remote_types_messages_proto_init() } +func file_core_capabilities_remote_types_messages_proto_init() { + if File_core_capabilities_remote_types_messages_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_core_capabilities_remote_types_messages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Message); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_capabilities_remote_types_messages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MessageBody); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_capabilities_remote_types_messages_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TriggerRegistrationMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_capabilities_remote_types_messages_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TriggerEventMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_core_capabilities_remote_types_messages_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoteTriggerConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_core_capabilities_remote_types_messages_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*MessageBody_TriggerRegistrationMetadata)(nil), + (*MessageBody_TriggerEventMetadata)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_core_capabilities_remote_types_messages_proto_rawDesc, + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_core_capabilities_remote_types_messages_proto_goTypes, + DependencyIndexes: file_core_capabilities_remote_types_messages_proto_depIdxs, + EnumInfos: file_core_capabilities_remote_types_messages_proto_enumTypes, + MessageInfos: file_core_capabilities_remote_types_messages_proto_msgTypes, + }.Build() + File_core_capabilities_remote_types_messages_proto = out.File + file_core_capabilities_remote_types_messages_proto_rawDesc = nil + file_core_capabilities_remote_types_messages_proto_goTypes = nil + file_core_capabilities_remote_types_messages_proto_depIdxs = nil +} diff --git a/core/capabilities/remote/types/message.proto b/core/capabilities/remote/types/messages.proto similarity index 85% rename from core/capabilities/remote/types/message.proto rename to core/capabilities/remote/types/messages.proto index 4d0507fd1e..a576e0e5fa 100644 --- a/core/capabilities/remote/types/message.proto +++ b/core/capabilities/remote/types/messages.proto @@ -48,3 +48,10 @@ message TriggerEventMetadata { string trigger_event_id = 1; repeated string workflow_ids = 2; } + +message RemoteTriggerConfig { + uint32 registrationRefreshMs = 1; + uint32 registrationExpiryMs = 2; + uint32 minResponsesToAggregate = 3; + uint32 messageExpiryMs = 4; +} diff --git a/core/capabilities/remote/types/mocks/receiver.go b/core/capabilities/remote/types/mocks/receiver.go index bc41baa549..b232912353 100644 --- a/core/capabilities/remote/types/mocks/receiver.go +++ b/core/capabilities/remote/types/mocks/receiver.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + types "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" mock "github.com/stretchr/testify/mock" ) @@ -12,9 +14,9 @@ type Receiver struct { mock.Mock } -// Receive provides a mock function with given fields: msg -func (_m *Receiver) Receive(msg *types.MessageBody) { - _m.Called(msg) +// Receive provides a mock function with given fields: ctx, msg +func (_m *Receiver) Receive(ctx context.Context, msg *types.MessageBody) { + _m.Called(ctx, msg) } // NewReceiver creates a new instance of Receiver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index a825c42be5..9c9cf67aa1 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -1,6 +1,12 @@ +// Note: the proto_path below directive ensures the generated protobuf's file descriptor has a fully +// qualified path, ensuring we avoid conflicts with other files called messages.proto +// +//go:generate protoc --proto_path=../../../../ --go_out=../../../../ --go_opt=paths=source_relative core/capabilities/remote/types/messages.proto package types import ( + "context" + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -21,7 +27,7 @@ type Dispatcher interface { //go:generate mockery --quiet --name Receiver --output ./mocks/ --case=underscore type Receiver interface { - Receive(msg *MessageBody) + Receive(ctx context.Context, msg *MessageBody) } type Aggregator interface { diff --git a/core/capabilities/streams/codec_test.go b/core/capabilities/streams/codec_test.go index 542f47c5e9..22100b0af5 100644 --- a/core/capabilities/streams/codec_test.go +++ b/core/capabilities/streams/codec_test.go @@ -93,12 +93,14 @@ func newFeedID(t *testing.T) ([32]byte, string) { func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) []byte { v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) raw, err := v3Codec.BuildReport(v3.ReportFields{ - BenchmarkPrice: price, - Timestamp: uint32(timestamp), - Bid: big.NewInt(0), - Ask: big.NewInt(0), - LinkFee: big.NewInt(0), - NativeFee: big.NewInt(0), + BenchmarkPrice: price, + Timestamp: uint32(timestamp), + ValidFromTimestamp: uint32(timestamp), + Bid: price, + Ask: price, + LinkFee: price, + NativeFee: price, + ExpiresAt: uint32(timestamp + 1000000), }) require.NoError(t, err) return raw diff --git a/core/capabilities/streams/trigger_test.go b/core/capabilities/streams/trigger_test.go new file mode 100644 index 0000000000..b8106e9212 --- /dev/null +++ b/core/capabilities/streams/trigger_test.go @@ -0,0 +1,224 @@ +package streams_test + +import ( + "crypto/ed25519" + "crypto/rand" + "math/big" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/require" + + ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +const ( + triggerID = "streams-trigger@1.0.0" + workflowID = "workflowID1" + baseTriggerEventID = "triggerEvent_" + basePrice = 2000000000 + baseTimestamp = 1000000000 +) + +type feed struct { + feedID [32]byte + feedIDStr string + reports []report +} + +type report struct { + rawReport []byte + reportCtx []byte + signatures [][]byte +} + +type node struct { + peerID p2ptypes.PeerID + bundle ocr2key.KeyBundle +} + +// Integration/load test that combines Trigger Subscriber, Streams Trigger Aggregator and Streams Codec. +// It measures time needed to receive and process trigger events from multiple nodes and produce a local aggregated event. +// For more meaningful measurements, increase the values of parameters P and T. +func TestStreamsTrigger(t *testing.T) { + N := 31 // trigger DON nodes + F := 10 // faulty nodes + R := 5 // different reports per feed (i.e. prices and timestamps) + P := 2 // feeds + T := 2 // test iterations + + nodes := newNodes(t, N) + feeds := newFeedsWithSignedReports(t, nodes, N, P, R) + + allowedSigners := make([][]byte, N) + for i := 0; i < N; i++ { + allowedSigners[i] = nodes[i].bundle.PublicKey() // bad name - see comment on evmKeyring.PublicKey + } + lggr := logger.TestLogger(t) + ctx := testutils.Context(t) + codec := streams.NewCodec(lggr) + agg := triggers.NewMercuryRemoteAggregator(codec, allowedSigners, F, lggr) + + capInfo := capabilities.CapabilityInfo{ + ID: triggerID, + } + capMembers := make([]p2ptypes.PeerID, N) + for i := 0; i < N; i++ { + capMembers[i] = nodes[i].peerID + } + capDonInfo := capabilities.DON{ + Members: capMembers, + F: uint8(F), + } + config := &remotetypes.RemoteTriggerConfig{ + MinResponsesToAggregate: uint32(F + 1), + } + subscriber := remote.NewTriggerSubscriber(config, capInfo, capDonInfo, capabilities.DON{}, nil, agg, lggr) + + // register trigger + req := capabilities.CapabilityRequest{ + Metadata: capabilities.RequestMetadata{ + WorkflowID: workflowID, + }, + } + triggerEventCallbackCh, err := subscriber.RegisterTrigger(ctx, req) + require.NoError(t, err) + + // send and process all trigger events + startTs := time.Now().UnixMilli() + processingTime := int64(0) + for c := 0; c < T; c++ { + triggerEventID := baseTriggerEventID + strconv.Itoa(c) + for i := 0; i < N; i++ { // every node ... + reportList := make([]datastreams.FeedReport, P) + for j := 0; j < P; j++ { // ... sends reports for every feed ... + reportIdx := (i + j) % R + signatures := make([][]byte, F+1) + for k := 0; k < F+1; k++ { // ... each signed by F+1 nodes + signatures[k] = feeds[j].reports[reportIdx].signatures[(i+k)%N] + } + signedStreamsReport := datastreams.FeedReport{ + FeedID: feeds[j].feedIDStr, + FullReport: feeds[j].reports[reportIdx].rawReport, + ReportContext: feeds[j].reports[reportIdx].reportCtx, + Signatures: signatures, + } + reportList[j] = signedStreamsReport + } + + msg := newTriggerEvent(t, reportList, triggerEventID, nodes[i].peerID) + + processingStart := time.Now().UnixMilli() + subscriber.Receive(ctx, msg) + processingTime += time.Now().UnixMilli() - processingStart + } + + response := <-triggerEventCallbackCh + validateLatestReports(t, response.Value, P, basePrice+R-1, baseTimestamp+R-1) + } + totalTime := time.Now().UnixMilli() - startTs + lggr.Infow("elapsed", "totalMs", totalTime, "processingMs", processingTime) +} + +func newNodes(t *testing.T, N int) []node { + nodes := make([]node, N) + for i := 0; i < N; i++ { + bundle, err := ocr2key.New(chaintype.EVM) + require.NoError(t, err) + nodes[i].bundle = bundle + nodes[i].peerID = newPeerID(t) + } + return nodes +} + +func newPeerID(t *testing.T) ragetypes.PeerID { + _, privKey, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err) + peerID, err := ragetypes.PeerIDFromPrivateKey(privKey) + require.NoError(t, err) + return peerID +} + +func newFeedsWithSignedReports(t *testing.T, nodes []node, N, P, R int) []feed { + feeds := make([]feed, P) + for i := 0; i < P; i++ { + id, idStr := newFeedID(t) + feeds[i].feedID = id + feeds[i].feedIDStr = idStr + feeds[i].reports = make([]report, R) + for j := 0; j < R; j++ { + report := newReport(t, id, big.NewInt(int64(basePrice+j)), int64(baseTimestamp+j)) + feeds[i].reports[j].rawReport = report + reportCtx := ocrTypes.ReportContext{ReportTimestamp: ocrTypes.ReportTimestamp{Epoch: uint32(baseTimestamp + j)}} + feeds[i].reports[j].reportCtx = rawReportContext(reportCtx) + feeds[i].reports[j].signatures = make([][]byte, N) + for k := 0; k < N; k++ { + signature, err := nodes[k].bundle.Sign(reportCtx, report) + require.NoError(t, err) + feeds[i].reports[j].signatures[k] = signature + } + } + } + return feeds +} + +func newTriggerEvent(t *testing.T, reportList []datastreams.FeedReport, triggerEventID string, sender ragetypes.PeerID) *remotetypes.MessageBody { + val, err := values.Wrap(reportList) + require.NoError(t, err) + + triggerEvent := capabilities.TriggerEvent{ + TriggerType: triggerID, + ID: triggerEventID, + Timestamp: strconv.FormatInt(1000, 10), + Metadata: nil, + Payload: val, + } + + eventVal, err := values.Wrap(triggerEvent) + require.NoError(t, err) + + marshaled, err := pb.MarshalCapabilityResponse(capabilities.CapabilityResponse{Value: eventVal}) + require.NoError(t, err) + msg := &remotetypes.MessageBody{ + Sender: sender[:], + Method: remotetypes.MethodTriggerEvent, + Metadata: &remotetypes.MessageBody_TriggerEventMetadata{ + TriggerEventMetadata: &remotetypes.TriggerEventMetadata{ + WorkflowIds: []string{workflowID}, + TriggerEventId: triggerEventID, + }, + }, + Payload: marshaled, + } + return msg +} + +func validateLatestReports(t *testing.T, wrapped values.Value, expectedFeedsLen int, expectedPrice int, expectedTimestamp int) { + triggerEvent := capabilities.TriggerEvent{} + require.NoError(t, wrapped.UnwrapTo(&triggerEvent)) + reports := []datastreams.FeedReport{} + require.NoError(t, triggerEvent.Payload.UnwrapTo(&reports)) + require.Equal(t, expectedFeedsLen, len(reports)) + priceBig := big.NewInt(int64(expectedPrice)) + for _, report := range reports { + require.Equal(t, priceBig.Bytes(), report.BenchmarkPrice) + require.Equal(t, int64(expectedTimestamp), report.ObservationTimestamp) + } +} diff --git a/core/capabilities/syncer.go b/core/capabilities/syncer.go index 3b40064667..800fb32509 100644 --- a/core/capabilities/syncer.go +++ b/core/capabilities/syncer.go @@ -2,36 +2,47 @@ package capabilities import ( "context" - "encoding/hex" + "errors" "fmt" "math/big" "slices" + "strings" "sync" "time" + "google.golang.org/protobuf/proto" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/core" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" "github.com/smartcontractkit/libocr/ragep2p" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) +type reader interface { + state(ctx context.Context) (state, error) + LocalNode(ctx context.Context) (capabilities.Node, error) +} + type registrySyncer struct { peerWrapper p2ptypes.PeerWrapper registry core.CapabilitiesRegistry dispatcher remotetypes.Dispatcher + stopCh services.StopChan subServices []services.Service networkSetup HardcodedDonNetworkSetup + reader wg sync.WaitGroup lggr logger.Logger @@ -39,6 +50,10 @@ type registrySyncer struct { var _ services.Service = ®istrySyncer{} +var ( + defaultTickInterval = 12 * time.Second +) + var defaultStreamConfig = p2ptypes.StreamConfig{ IncomingMessageBufferSize: 1000000, OutgoingMessageBufferSize: 1000000, @@ -53,172 +68,652 @@ var defaultStreamConfig = p2ptypes.StreamConfig{ }, } -const maxRetryCount = 60 - // RegistrySyncer updates local Registry to match its onchain counterpart -func NewRegistrySyncer(peerWrapper p2ptypes.PeerWrapper, registry core.CapabilitiesRegistry, dispatcher remotetypes.Dispatcher, lggr logger.Logger, - networkSetup HardcodedDonNetworkSetup) *registrySyncer { +func NewRegistrySyncer( + peerWrapper p2ptypes.PeerWrapper, + registry core.CapabilitiesRegistry, + dispatcher remotetypes.Dispatcher, + lggr logger.Logger, + networkSetup HardcodedDonNetworkSetup, + relayer contractReaderFactory, + registryAddress string, +) (*registrySyncer, error) { + stopCh := make(services.StopChan) + ctx, _ := stopCh.NewCtx() + reader, err := newRemoteRegistryReader(ctx, lggr, peerWrapper, relayer, registryAddress) + if err != nil { + return nil, err + } + + return newRegistrySyncer( + stopCh, + peerWrapper, + registry, + dispatcher, + lggr.Named("RegistrySyncer"), + networkSetup, + reader, + ), nil +} + +func newRegistrySyncer( + stopCh services.StopChan, + peerWrapper p2ptypes.PeerWrapper, + registry core.CapabilitiesRegistry, + dispatcher remotetypes.Dispatcher, + lggr logger.Logger, + networkSetup HardcodedDonNetworkSetup, + reader reader, +) *registrySyncer { return ®istrySyncer{ + stopCh: stopCh, peerWrapper: peerWrapper, registry: registry, dispatcher: dispatcher, networkSetup: networkSetup, lggr: lggr, + reader: reader, } } func (s *registrySyncer) Start(ctx context.Context) error { + // NOTE: Decrease wg.Add and uncomment the line below + // `go s.launch()` to enable the hardcoded syncer. s.wg.Add(1) - go s.launch(context.Background()) + // go s.launch() + go s.syncLoop() return nil } -// NOTE: this implementation of the Syncer is temporary and will be replaced by one -// that reads the configuration from chain (KS-117). -func (s *registrySyncer) launch(ctx context.Context) { +func (s *registrySyncer) syncLoop() { defer s.wg.Done() - capId := "streams-trigger@1.0.0" - triggerInfo, err := capabilities.NewRemoteCapabilityInfo( - capId, - capabilities.CapabilityTypeTrigger, - "Remote Trigger", - &s.networkSetup.TriggerCapabilityDonInfo, - ) + + ctx, cancel := s.stopCh.NewCtx() + defer cancel() + + ticker := time.NewTicker(defaultTickInterval) + defer ticker.Stop() + + // Sync for a first time outside the loop; this means we'll start a remote + // sync immediately once spinning up syncLoop, as by default a ticker will + // fire for the first time at T+N, where N is the interval. + s.lggr.Debug("starting initial sync with remote registry") + err := s.sync(ctx) if err != nil { - s.lggr.Errorw("failed to create capability info for streams-trigger", "error", err) - return + s.lggr.Errorw("failed to sync with remote registry", "error", err) } - targetCapId := "write_ethereum-testnet-sepolia@1.0.0" - targetInfo, err := capabilities.NewRemoteCapabilityInfo( - targetCapId, - capabilities.CapabilityTypeTarget, - "Remote Target", - &s.networkSetup.TargetCapabilityDonInfo, - ) + for { + select { + case <-s.stopCh: + return + case <-ticker.C: + s.lggr.Debug("starting regular sync with the remote registry") + err := s.sync(ctx) + if err != nil { + s.lggr.Errorw("failed to sync with remote registry", "error", err) + } + } + } +} + +func (s *registrySyncer) sync(ctx context.Context) error { + readerState, err := s.reader.state(ctx) if err != nil { - s.lggr.Errorw("failed to create capability info for write_ethereum-testnet-sepolia", "error", err) - return + return fmt.Errorf("failed to sync with remote registry: %w", err) + } + + // Let's start by updating the list of Peers + // We do this by creating a new entry for each node belonging + // to a public DON. + // We also add the hardcoded peers determined by the NetworkSetup. + allPeers := make(map[ragetypes.PeerID]p2ptypes.StreamConfig) + // TODO: Remove this when we're no longer hard-coding + // a `networkSetup`. + for p, cfg := range s.networkSetup.allPeers { + allPeers[p] = cfg } - myId := s.peerWrapper.GetPeer().ID() - config := remotetypes.RemoteTriggerConfig{ - RegistrationRefreshMs: 20000, - RegistrationExpiryMs: 60000, - MinResponsesToAggregate: uint32(s.networkSetup.TriggerCapabilityDonInfo.F) + 1, + publicDONs := []kcr.CapabilitiesRegistryDONInfo{} + for _, d := range readerState.IDsToDONs { + if !d.IsPublic { + continue + } + + publicDONs = append(publicDONs, d) + + for _, nid := range d.NodeP2PIds { + allPeers[nid] = defaultStreamConfig + } } - err = s.peerWrapper.GetPeer().UpdateConnections(s.networkSetup.allPeers) + + // TODO: be a bit smarter about who we connect to; we should ideally only + // be connecting to peers when we need to. + // https://smartcontract-it.atlassian.net/browse/KS-330 + err = s.peerWrapper.GetPeer().UpdateConnections(allPeers) if err != nil { - s.lggr.Errorw("failed to update connections", "error", err) - return - } - if s.networkSetup.IsWorkflowDon(myId) { - s.lggr.Info("member of a workflow DON - starting remote subscribers") - codec := streams.NewCodec(s.lggr) - aggregator := triggers.NewMercuryRemoteAggregator(codec, hexStringsToBytes(s.networkSetup.triggerDonSigners), int(s.networkSetup.TriggerCapabilityDonInfo.F+1), s.lggr) - triggerCap := remote.NewTriggerSubscriber(config, triggerInfo, s.networkSetup.TriggerCapabilityDonInfo, s.networkSetup.WorkflowsDonInfo, s.dispatcher, aggregator, s.lggr) - err = s.registry.Add(ctx, triggerCap) - if err != nil { - s.lggr.Errorw("failed to add remote trigger capability to registry", "error", err) - return + return fmt.Errorf("failed to update peer connections: %w", err) + } + + // Next, we need to split the DONs into the following: + // - workflow DONs the current node is a part of. + // These will need remote shims to all remote capabilities on other DONs. + // + // We'll also construct a set to record what DONs the current node is a part of, + // regardless of any modifiers (public/acceptsWorkflows etc). + myID := s.peerWrapper.GetPeer().ID() + myWorkflowDONs := []kcr.CapabilitiesRegistryDONInfo{} + remoteWorkflowDONs := []kcr.CapabilitiesRegistryDONInfo{} + myDONs := map[uint32]bool{} + for _, d := range readerState.IDsToDONs { + for _, peerID := range d.NodeP2PIds { + if peerID == myID { + myDONs[d.Id] = true + } } - err = s.dispatcher.SetReceiver(capId, s.networkSetup.TriggerCapabilityDonInfo.ID, triggerCap) - if err != nil { - s.lggr.Errorw("workflow DON failed to set receiver for trigger", "capabilityId", capId, "donId", s.networkSetup.TriggerCapabilityDonInfo.ID, "error", err) - return + + if d.AcceptsWorkflows { + if myDONs[d.Id] { + myWorkflowDONs = append(myWorkflowDONs, d) + } else { + remoteWorkflowDONs = append(remoteWorkflowDONs, d) + } } - s.subServices = append(s.subServices, triggerCap) + } - s.lggr.Info("member of a workflow DON - starting remote targets") - targetCap := target.NewClient(targetInfo, s.networkSetup.WorkflowsDonInfo, s.dispatcher, 60*time.Second, s.lggr) - err = s.registry.Add(ctx, targetCap) - if err != nil { - s.lggr.Errorw("failed to add remote target capability to registry", "error", err) - return + // - remote capability DONs (with IsPublic = true) the current node is a part of. + // These need server-side shims. + myCapabilityDONs := []kcr.CapabilitiesRegistryDONInfo{} + remoteCapabilityDONs := []kcr.CapabilitiesRegistryDONInfo{} + for _, d := range publicDONs { + if len(d.CapabilityConfigurations) > 0 { + if myDONs[d.Id] { + myCapabilityDONs = append(myCapabilityDONs, d) + } else { + remoteCapabilityDONs = append(remoteCapabilityDONs, d) + } } - err = s.dispatcher.SetReceiver(targetCapId, s.networkSetup.TargetCapabilityDonInfo.ID, targetCap) - if err != nil { - s.lggr.Errorw("workflow DON failed to set receiver for target", "capabilityId", capId, "donId", s.networkSetup.TargetCapabilityDonInfo.ID, "error", err) - return + } + + // Now, if my node is a workflow DON, let's setup any shims + // to external capabilities. + if len(myWorkflowDONs) > 0 { + myDON := myWorkflowDONs[0] + + // TODO: this is a bit nasty; figure out how best to handle this. + if len(myWorkflowDONs) > 1 { + s.lggr.Warn("node is part of more than one workflow DON; assigning first DON as caller") + } + + for _, rcd := range remoteCapabilityDONs { + err := s.addRemoteCapabilities(ctx, myDON, rcd, readerState) + if err != nil { + return err + } } - s.subServices = append(s.subServices, targetCap) } - if s.networkSetup.IsTriggerDon(myId) { - s.lggr.Info("member of a capability DON - starting remote publishers") - /*{ - // ---- This is for local tests only, until a full-blown Syncer is implemented - // ---- Normally this is set up asynchronously (by the Relayer + job specs in Mercury's case) - localTrigger := triggers.NewMercuryTriggerService(1000, s.lggr) - mockMercuryDataProducer := NewMockMercuryDataProducer(localTrigger, s.lggr) - err = s.registry.Add(ctx, localTrigger) + // Finally, if I'm a capability DON, let's enable external access + // to the capability. + if len(myCapabilityDONs) > 0 { + for _, mcd := range myCapabilityDONs { + err := s.enableExternalAccess(ctx, myID, mcd, readerState, remoteWorkflowDONs) if err != nil { - s.lggr.Errorw("failed to add local trigger capability to registry", "error", err) return err } - s.subServices = append(s.subServices, localTrigger) - s.subServices = append(s.subServices, mockMercuryDataProducer) - // ---- - }*/ - - count := 0 - for { - count++ - if count > maxRetryCount { - s.lggr.Error("failed to get Streams Trigger from the Registry") - return + } + } + + return nil +} + +func signersFor(don kcr.CapabilitiesRegistryDONInfo, state state) ([][]byte, error) { + s := [][]byte{} + for _, nodeID := range don.NodeP2PIds { + node, ok := state.IDsToNodes[nodeID] + if !ok { + return nil, fmt.Errorf("could not find node for id %s", nodeID) + } + + // NOTE: the capability registry stores signers as [32]byte, + // but we only need the first [20], as the rest is padded. + s = append(s, node.Signer[0:20]) + } + + return s, nil +} + +func toDONInfo(don kcr.CapabilitiesRegistryDONInfo) *capabilities.DON { + peerIDs := []p2ptypes.PeerID{} + for _, p := range don.NodeP2PIds { + peerIDs = append(peerIDs, p) + } + + return &capabilities.DON{ + ID: fmt.Sprint(don.Id), + Members: peerIDs, + F: don.F, + } +} + +func toCapabilityType(capabilityType uint8) capabilities.CapabilityType { + switch capabilityType { + case 0: + return capabilities.CapabilityTypeTrigger + case 1: + return capabilities.CapabilityTypeAction + case 2: + return capabilities.CapabilityTypeConsensus + case 3: + return capabilities.CapabilityTypeTarget + default: + // Not found + return capabilities.CapabilityType(-1) + } +} + +func (s *registrySyncer) addRemoteCapabilities(ctx context.Context, myDON kcr.CapabilitiesRegistryDONInfo, remoteDON kcr.CapabilitiesRegistryDONInfo, state state) error { + for _, c := range remoteDON.CapabilityConfigurations { + capability, ok := state.IDsToCapabilities[c.CapabilityId] + if !ok { + return fmt.Errorf("could not find capability matching id %s", c.CapabilityId) + } + + switch toCapabilityType(capability.CapabilityType) { + case capabilities.CapabilityTypeTrigger: + newTriggerFn := func(info capabilities.CapabilityInfo) (capabilityService, error) { + if !strings.HasPrefix(info.ID, "streams-trigger") { + return nil, errors.New("not supported: trigger capability does not have id = streams-trigger") + } + + codec := streams.NewCodec(s.lggr) + + signers, err := signersFor(remoteDON, state) + if err != nil { + return nil, err + } + + aggregator := triggers.NewMercuryRemoteAggregator( + codec, + signers, + int(remoteDON.F+1), + s.lggr, + ) + cfg := &remotetypes.RemoteTriggerConfig{} + cfg.ApplyDefaults() + err = proto.Unmarshal(c.Config, cfg) + if err != nil { + return nil, err + } + // TODO: We need to implement a custom, Mercury-specific + // aggregator here, because there is no guarantee that + // all trigger events in the workflow will have the same + // payloads. As a workaround, we validate the signatures. + // When this is solved, we can move to a generic aggregator + // and remove this. + triggerCap := remote.NewTriggerSubscriber( + cfg, + info, + *toDONInfo(remoteDON), + *toDONInfo(myDON), + s.dispatcher, + aggregator, + s.lggr, + ) + return triggerCap, nil } - underlying, err2 := s.registry.GetTrigger(ctx, capId) - if err2 != nil { - // NOTE: it's possible that the jobs are not launched yet at this moment. - // If not found yet, Syncer won't add to Registry but retry on the next tick. - s.lggr.Infow("trigger not found yet ...", "capabilityId", capId, "error", err2) - time.Sleep(1 * time.Second) - continue + err := s.addToRegistryAndSetDispatcher(ctx, capability, remoteDON, newTriggerFn) + if err != nil { + return fmt.Errorf("failed to add trigger shim: %w", err) } - workflowDONs := map[string]capabilities.DON{ - s.networkSetup.WorkflowsDonInfo.ID: s.networkSetup.WorkflowsDonInfo, + case capabilities.CapabilityTypeAction: + s.lggr.Warn("no remote client configured for capability type action, skipping configuration") + case capabilities.CapabilityTypeConsensus: + s.lggr.Warn("no remote client configured for capability type consensus, skipping configuration") + case capabilities.CapabilityTypeTarget: + newTargetFn := func(info capabilities.CapabilityInfo) (capabilityService, error) { + client := target.NewClient( + info, + *toDONInfo(myDON), + s.dispatcher, + defaultTargetRequestTimeout, + s.lggr, + ) + return client, nil } - triggerCap := remote.NewTriggerPublisher(config, underlying, triggerInfo, s.networkSetup.TriggerCapabilityDonInfo, workflowDONs, s.dispatcher, s.lggr) - err = s.dispatcher.SetReceiver(capId, s.networkSetup.TriggerCapabilityDonInfo.ID, triggerCap) + + err := s.addToRegistryAndSetDispatcher(ctx, capability, remoteDON, newTargetFn) if err != nil { - s.lggr.Errorw("capability DON failed to set receiver", "capabilityId", capId, "donId", s.networkSetup.TriggerCapabilityDonInfo.ID, "error", err) - return + return fmt.Errorf("failed to add target shim: %w", err) } - s.subServices = append(s.subServices, triggerCap) - break + default: + s.lggr.Warnf("unknown capability type, skipping configuration: %+v", capability) } } - if s.networkSetup.IsTargetDon(myId) { - s.lggr.Info("member of a target DON - starting remote shims") - underlying, err2 := s.registry.GetTarget(ctx, targetCapId) - if err2 != nil { - s.lggr.Errorw("target not found yet", "capabilityId", targetCapId, "error", err2) - return + return nil +} + +type capabilityService interface { + capabilities.BaseCapability + remotetypes.Receiver + services.Service +} + +func (s *registrySyncer) addToRegistryAndSetDispatcher(ctx context.Context, capabilityInfo kcr.CapabilitiesRegistryCapabilityInfo, don kcr.CapabilitiesRegistryDONInfo, newCapFn func(info capabilities.CapabilityInfo) (capabilityService, error)) error { + fullCapID := fmt.Sprintf("%s@%s", capabilityInfo.LabelledName, capabilityInfo.Version) + info, err := capabilities.NewRemoteCapabilityInfo( + fullCapID, + toCapabilityType(capabilityInfo.CapabilityType), + fmt.Sprintf("Remote Capability for %s", fullCapID), + toDONInfo(don), + ) + if err != nil { + return err + } + s.lggr.Debugw("Adding remote capability to registry", "id", info.ID, "don", info.DON) + capability, err := newCapFn(info) + if err != nil { + return err + } + + err = s.registry.Add(ctx, capability) + if err != nil { + // If the capability already exists, then it's either local + // or we've handled this in a previous syncer iteration, + // let's skip and move on to other capabilities. + if errors.Is(err, ErrCapabilityAlreadyExists) { + return nil } - workflowDONs := map[string]capabilities.DON{ - s.networkSetup.WorkflowsDonInfo.ID: s.networkSetup.WorkflowsDonInfo, + + return err + } + + err = s.dispatcher.SetReceiver( + fullCapID, + fmt.Sprint(don.Id), + capability, + ) + if err != nil { + return err + } + s.lggr.Debugw("Setting receiver for capability", "id", fullCapID, "donID", don.Id) + err = capability.Start(ctx) + if err != nil { + return err + } + s.subServices = append(s.subServices, capability) + return nil +} + +var ( + defaultTargetRequestTimeout = time.Minute +) + +func (s *registrySyncer) enableExternalAccess(ctx context.Context, myPeerID p2ptypes.PeerID, don kcr.CapabilitiesRegistryDONInfo, state state, remoteWorkflowDONs []kcr.CapabilitiesRegistryDONInfo) error { + idsToDONs := map[string]capabilities.DON{} + for _, d := range remoteWorkflowDONs { + idsToDONs[fmt.Sprint(d.Id)] = *toDONInfo(d) + } + + for _, c := range don.CapabilityConfigurations { + capability, ok := state.IDsToCapabilities[c.CapabilityId] + if !ok { + return fmt.Errorf("could not find capability matching id %s", c.CapabilityId) } - targetCap := target.NewServer(myId, underlying, targetInfo, *targetInfo.DON, workflowDONs, s.dispatcher, 60*time.Second, s.lggr) - err = s.dispatcher.SetReceiver(targetCapId, s.networkSetup.TargetCapabilityDonInfo.ID, targetCap) - if err != nil { - s.lggr.Errorw("capability DON failed to set receiver", "capabilityId", capId, "donId", s.networkSetup.TargetCapabilityDonInfo.ID, "error", err) - return + + switch toCapabilityType(capability.CapabilityType) { + case capabilities.CapabilityTypeTrigger: + newTriggerPublisher := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error) { + cfg := &remotetypes.RemoteTriggerConfig{} + cfg.ApplyDefaults() + err := proto.Unmarshal(c.Config, cfg) + if err != nil { + return nil, err + } + publisher := remote.NewTriggerPublisher( + cfg, + capability.(capabilities.TriggerCapability), + info, + *toDONInfo(don), + idsToDONs, + s.dispatcher, + s.lggr, + ) + return publisher, nil + } + + err := s.addReceiver(ctx, capability, don, newTriggerPublisher) + if err != nil { + return fmt.Errorf("failed to add server-side receiver: %w", err) + } + case capabilities.CapabilityTypeAction: + s.lggr.Warn("no remote client configured for capability type action, skipping configuration") + case capabilities.CapabilityTypeConsensus: + s.lggr.Warn("no remote client configured for capability type consensus, skipping configuration") + case capabilities.CapabilityTypeTarget: + newTargetServer := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error) { + return target.NewServer( + myPeerID, + capability.(capabilities.TargetCapability), + info, + *toDONInfo(don), + idsToDONs, + s.dispatcher, + defaultTargetRequestTimeout, + s.lggr, + ), nil + } + + err := s.addReceiver(ctx, capability, don, newTargetServer) + if err != nil { + return fmt.Errorf("failed to add server-side receiver: %w", err) + } + default: + s.lggr.Warnf("unknown capability type, skipping configuration: %+v", capability) } - s.subServices = append(s.subServices, targetCap) } - // NOTE: temporary service start - should be managed by capability creation - for _, srv := range s.subServices { - err = srv.Start(ctx) - if err != nil { - s.lggr.Errorw("failed to start remote trigger caller", "error", err) - return - } + return nil +} + +type receiverService interface { + services.Service + remotetypes.Receiver +} + +func (s *registrySyncer) addReceiver(ctx context.Context, capability kcr.CapabilitiesRegistryCapabilityInfo, don kcr.CapabilitiesRegistryDONInfo, newReceiverFn func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error)) error { + fullCapID := fmt.Sprintf("%s@%s", capability.LabelledName, capability.Version) + info, err := capabilities.NewRemoteCapabilityInfo( + fullCapID, + toCapabilityType(capability.CapabilityType), + fmt.Sprintf("Remote Capability for %s", fullCapID), + toDONInfo(don), + ) + if err != nil { + return err + } + underlying, err := s.registry.Get(ctx, fullCapID) + if err != nil { + return err + } + + receiver, err := newReceiverFn(underlying, info) + if err != nil { + return err + } + + s.lggr.Debugw("Enabling external access for capability", "id", fullCapID, "donID", don.Id) + err = s.dispatcher.SetReceiver(fullCapID, fmt.Sprint(don.Id), receiver) + if err != nil { + return err } - s.lggr.Info("registry syncer started") + + err = receiver.Start(ctx) + if err != nil { + return err + } + + s.subServices = append(s.subServices, receiver) + return nil } +//func hexStringsToBytes(strs []string) (res [][]byte) { +// for _, s := range strs { +// b, _ := hex.DecodeString(s[2:]) +// res = append(res, b) +// } +// return res +//} + +//const maxRetryCount = 60 + +//// NOTE: this implementation of the Syncer is temporary and will be replaced by one +//// that reads the configuration from chain (KS-117). +//func (s *registrySyncer) launch() { +// ctx, _ := s.stopCh.NewCtx() +// defer s.wg.Done() +// capId := "streams-trigger@1.0.0" +// triggerInfo, err := capabilities.NewRemoteCapabilityInfo( +// capId, +// capabilities.CapabilityTypeTrigger, +// "Remote Trigger", +// &s.networkSetup.TriggerCapabilityDonInfo, +// ) +// if err != nil { +// s.lggr.Errorw("failed to create capability info for streams-trigger", "error", err) +// return +// } +// +// targetCapId := "write_ethereum-testnet-sepolia@1.0.0" +// targetInfo, err := capabilities.NewRemoteCapabilityInfo( +// targetCapId, +// capabilities.CapabilityTypeTarget, +// "Remote Target", +// &s.networkSetup.TargetCapabilityDonInfo, +// ) +// if err != nil { +// s.lggr.Errorw("failed to create capability info for write_ethereum-testnet-sepolia", "error", err) +// return +// } +// +// myId := s.peerWrapper.GetPeer().ID() +// config := &remotetypes.RemoteTriggerConfig{ +// RegistrationRefreshMs: 20000, +// RegistrationExpiryMs: 60000, +// MinResponsesToAggregate: uint32(s.networkSetup.TriggerCapabilityDonInfo.F) + 1, +// } +// err = s.peerWrapper.GetPeer().UpdateConnections(s.networkSetup.allPeers) +// if err != nil { +// s.lggr.Errorw("failed to update connections", "error", err) +// return +// } +// if s.networkSetup.IsWorkflowDon(myId) { +// s.lggr.Info("member of a workflow DON - starting remote subscribers") +// codec := streams.NewCodec(s.lggr) +// aggregator := triggers.NewMercuryRemoteAggregator(codec, hexStringsToBytes(s.networkSetup.triggerDonSigners), int(s.networkSetup.TriggerCapabilityDonInfo.F+1), s.lggr) +// triggerCap := remote.NewTriggerSubscriber(config, triggerInfo, s.networkSetup.TriggerCapabilityDonInfo, s.networkSetup.WorkflowsDonInfo, s.dispatcher, aggregator, s.lggr) +// err = s.registry.Add(ctx, triggerCap) +// if err != nil { +// s.lggr.Errorw("failed to add remote trigger capability to registry", "error", err) +// return +// } +// err = s.dispatcher.SetReceiver(capId, s.networkSetup.TriggerCapabilityDonInfo.ID, triggerCap) +// if err != nil { +// s.lggr.Errorw("workflow DON failed to set receiver for trigger", "capabilityId", capId, "donId", s.networkSetup.TriggerCapabilityDonInfo.ID, "error", err) +// return +// } +// s.subServices = append(s.subServices, triggerCap) +// +// s.lggr.Info("member of a workflow DON - starting remote targets") +// targetCap := target.NewClient(targetInfo, s.networkSetup.WorkflowsDonInfo, s.dispatcher, 60*time.Second, s.lggr) +// err = s.registry.Add(ctx, targetCap) +// if err != nil { +// s.lggr.Errorw("failed to add remote target capability to registry", "error", err) +// return +// } +// err = s.dispatcher.SetReceiver(targetCapId, s.networkSetup.TargetCapabilityDonInfo.ID, targetCap) +// if err != nil { +// s.lggr.Errorw("workflow DON failed to set receiver for target", "capabilityId", capId, "donId", s.networkSetup.TargetCapabilityDonInfo.ID, "error", err) +// return +// } +// s.subServices = append(s.subServices, targetCap) +// } +// if s.networkSetup.IsTriggerDon(myId) { +// s.lggr.Info("member of a capability DON - starting remote publishers") +// +// /*{ +// // ---- This is for local tests only, until a full-blown Syncer is implemented +// // ---- Normally this is set up asynchronously (by the Relayer + job specs in Mercury's case) +// localTrigger := triggers.NewMercuryTriggerService(1000, s.lggr) +// mockMercuryDataProducer := NewMockMercuryDataProducer(localTrigger, s.lggr) +// err = s.registry.Add(ctx, localTrigger) +// if err != nil { +// s.lggr.Errorw("failed to add local trigger capability to registry", "error", err) +// return err +// } +// s.subServices = append(s.subServices, localTrigger) +// s.subServices = append(s.subServices, mockMercuryDataProducer) +// // ---- +// }*/ +// +// count := 0 +// for { +// count++ +// if count > maxRetryCount { +// s.lggr.Error("failed to get Streams Trigger from the Registry") +// return +// } +// underlying, err2 := s.registry.GetTrigger(ctx, capId) +// if err2 != nil { +// // NOTE: it's possible that the jobs are not launched yet at this moment. +// // If not found yet, Syncer won't add to Registry but retry on the next tick. +// s.lggr.Infow("trigger not found yet ...", "capabilityId", capId, "error", err2) +// time.Sleep(1 * time.Second) +// continue +// } +// workflowDONs := map[string]capabilities.DON{ +// s.networkSetup.WorkflowsDonInfo.ID: s.networkSetup.WorkflowsDonInfo, +// } +// triggerCap := remote.NewTriggerPublisher(config, underlying, triggerInfo, s.networkSetup.TriggerCapabilityDonInfo, workflowDONs, s.dispatcher, s.lggr) +// err = s.dispatcher.SetReceiver(capId, s.networkSetup.TriggerCapabilityDonInfo.ID, triggerCap) +// if err != nil { +// s.lggr.Errorw("capability DON failed to set receiver", "capabilityId", capId, "donId", s.networkSetup.TriggerCapabilityDonInfo.ID, "error", err) +// return +// } +// s.subServices = append(s.subServices, triggerCap) +// break +// } +// } +// if s.networkSetup.IsTargetDon(myId) { +// s.lggr.Info("member of a target DON - starting remote shims") +// underlying, err2 := s.registry.GetTarget(ctx, targetCapId) +// if err2 != nil { +// s.lggr.Errorw("target not found yet", "capabilityId", targetCapId, "error", err2) +// return +// } +// workflowDONs := map[string]capabilities.DON{ +// s.networkSetup.WorkflowsDonInfo.ID: s.networkSetup.WorkflowsDonInfo, +// } +// targetCap := target.NewServer(myId, underlying, targetInfo, *targetInfo.DON, workflowDONs, s.dispatcher, 60*time.Second, s.lggr) +// err = s.dispatcher.SetReceiver(targetCapId, s.networkSetup.TargetCapabilityDonInfo.ID, targetCap) +// if err != nil { +// s.lggr.Errorw("capability DON failed to set receiver", "capabilityId", capId, "donId", s.networkSetup.TargetCapabilityDonInfo.ID, "error", err) +// return +// } +// s.subServices = append(s.subServices, targetCap) +// } +// // NOTE: temporary service start - should be managed by capability creation +// for _, srv := range s.subServices { +// err = srv.Start(ctx) +// if err != nil { +// s.lggr.Errorw("failed to start remote trigger caller", "error", err) +// return +// } +// } +// s.lggr.Info("registry syncer started") +//} + func (s *registrySyncer) Close() error { + close(s.stopCh) s.wg.Wait() for _, subService := range s.subServices { err := subService.Close() @@ -262,6 +757,9 @@ func NewHardcodedDonNetworkSetup() (HardcodedDonNetworkSetup, error) { "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", + "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97", + "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA", + "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX", } result.triggerDonPeers = []string{ "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m", @@ -301,7 +799,7 @@ func NewHardcodedDonNetworkSetup() (HardcodedDonNetworkSetup, error) { } return nil } - result.WorkflowsDonInfo = capabilities.DON{ID: "workflowDon1", F: 1} + result.WorkflowsDonInfo = capabilities.DON{ID: "workflowDon1", F: 2} if err := addPeersToDONInfo(result.workflowDonPeers, &result.WorkflowsDonInfo); err != nil { return HardcodedDonNetworkSetup{}, fmt.Errorf("failed to add peers to workflow DON info: %w", err) } @@ -413,11 +911,3 @@ func (m *mockMercuryDataProducer) Ready() error { func (m *mockMercuryDataProducer) Name() string { return "mockMercuryDataProducer" } - -func hexStringsToBytes(strs []string) (res [][]byte) { - for _, s := range strs { - b, _ := hex.DecodeString(s[2:]) - res = append(res, b) - } - return res -} diff --git a/core/capabilities/syncer_test.go b/core/capabilities/syncer_test.go index a654f303a9..2c5f871bdb 100644 --- a/core/capabilities/syncer_test.go +++ b/core/capabilities/syncer_test.go @@ -1,18 +1,25 @@ -package capabilities_test +package capabilities import ( + "context" + "fmt" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" commonMocks "github.com/smartcontractkit/chainlink-common/pkg/types/mocks" - coreCapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" remoteMocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types/mocks" ) @@ -28,13 +35,579 @@ func TestSyncer_CleanStartClose(t *testing.T) { wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) registry := commonMocks.NewCapabilitiesRegistry(t) - registry.On("Add", mock.Anything, mock.Anything).Return(nil) dispatcher := remoteMocks.NewDispatcher(t) - dispatcher.On("SetReceiver", mock.Anything, mock.Anything, mock.Anything).Return(nil) - networkSetup, err := coreCapabilities.NewHardcodedDonNetworkSetup() + networkSetup, err := NewHardcodedDonNetworkSetup() + require.NoError(t, err) + mr := &mockReader{} + syncer := newRegistrySyncer(make(services.StopChan), wrapper, registry, dispatcher, lggr, networkSetup, mr) require.NoError(t, err) - syncer := coreCapabilities.NewRegistrySyncer(wrapper, registry, dispatcher, lggr, networkSetup) require.NoError(t, syncer.Start(ctx)) require.NoError(t, syncer.Close()) } + +type mockReader struct { + s state + err error +} + +func (m mockReader) state(ctx context.Context) (state, error) { + return m.s, m.err +} + +func (m mockReader) LocalNode(ctx context.Context) (capabilities.Node, error) { + return capabilities.Node{}, nil +} + +type mockTrigger struct { + capabilities.CapabilityInfo +} + +func (m *mockTrigger) RegisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { + return nil, nil +} + +func (m *mockTrigger) UnregisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) error { + return nil +} + +func newMockTrigger(info capabilities.CapabilityInfo) *mockTrigger { + return &mockTrigger{CapabilityInfo: info} +} + +type mockCapability struct { + capabilities.CapabilityInfo +} + +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { + return nil, nil +} + +func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { + return nil +} + +func (m *mockCapability) UnregisterFromWorkflow(ctx context.Context, request capabilities.UnregisterFromWorkflowRequest) error { + return nil +} + +func TestSyncer_WiresUpExternalCapabilities(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + registry := NewRegistry(lggr) + dispatcher := remoteMocks.NewDispatcher(t) + + var pid ragetypes.PeerID + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) + require.NoError(t, err) + peer := mocks.NewPeer(t) + peer.On("UpdateConnections", mock.Anything).Return(nil) + peer.On("ID").Return(pid) + wrapper := mocks.NewPeerWrapper(t) + wrapper.On("GetPeer").Return(peer) + + nodes := [][32]byte{ + pid, + randomWord(), + randomWord(), + randomWord(), + } + + fullTriggerCapID := "streams-trigger@1.0.0" + mt := newMockTrigger(capabilities.MustNewCapabilityInfo( + fullTriggerCapID, + capabilities.CapabilityTypeTrigger, + "streams trigger", + )) + require.NoError(t, registry.Add(ctx, mt)) + + fullTargetID := "write-chain_evm_1@1.0.0" + mtarg := &mockCapability{ + CapabilityInfo: capabilities.MustNewCapabilityInfo( + fullTargetID, + capabilities.CapabilityTypeTarget, + "write chain", + ), + } + require.NoError(t, registry.Add(ctx, mtarg)) + + triggerCapID := randomWord() + targetCapID := randomWord() + dID := uint32(1) + // The below state describes a Workflow DON (AcceptsWorkflows = true), + // which exposes the streams-trigger and write_chain capabilities. + // We expect a publisher to be wired up with this configuration, and + // no entries should be added to the registry. + mr := &mockReader{ + s: state{ + IDsToDONs: map[donID]kcr.CapabilitiesRegistryDONInfo{ + donID(dID): { + Id: dID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + NodeP2PIds: nodes, + CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: triggerCapID, + Config: []byte(""), + }, + { + CapabilityId: targetCapID, + Config: []byte(""), + }, + }, + }, + }, + IDsToCapabilities: map[hashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ + triggerCapID: { + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: 0, + }, + targetCapID: { + LabelledName: "write-chain_evm_1", + Version: "1.0.0", + CapabilityType: 3, + }, + }, + IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + nodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[0], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + nodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[1], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + nodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[2], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + nodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[3], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + }, + }, + } + syncer := newRegistrySyncer(make(services.StopChan), wrapper, registry, dispatcher, lggr, HardcodedDonNetworkSetup{}, mr) + require.NoError(t, err) + + dispatcher.On("SetReceiver", fullTriggerCapID, fmt.Sprint(dID), mock.AnythingOfType("*remote.triggerPublisher")).Return(nil) + dispatcher.On("SetReceiver", fullTargetID, fmt.Sprint(dID), mock.AnythingOfType("*target.server")).Return(nil) + + err = syncer.sync(ctx) + require.NoError(t, err) + defer syncer.Close() +} + +func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + registry := NewRegistry(lggr) + dispatcher := remoteMocks.NewDispatcher(t) + + var pid ragetypes.PeerID + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) + require.NoError(t, err) + peer := mocks.NewPeer(t) + peer.On("UpdateConnections", mock.Anything).Return(nil) + peer.On("ID").Return(pid) + wrapper := mocks.NewPeerWrapper(t) + wrapper.On("GetPeer").Return(peer) + + nodes := [][32]byte{ + pid, + randomWord(), + randomWord(), + randomWord(), + } + + triggerCapID := randomWord() + targetCapID := randomWord() + dID := uint32(1) + // The below state describes a Workflow DON (AcceptsWorkflows = true), + // which isn't public (IsPublic = false), but hosts the + // the streams-trigger and write_chain capabilities. + // We expect no action to be taken by the syncer. + mr := &mockReader{ + s: state{ + IDsToDONs: map[donID]kcr.CapabilitiesRegistryDONInfo{ + donID(dID): { + Id: dID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: false, + AcceptsWorkflows: true, + NodeP2PIds: nodes, + CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: triggerCapID, + Config: []byte(""), + }, + { + CapabilityId: targetCapID, + Config: []byte(""), + }, + }, + }, + }, + IDsToCapabilities: map[hashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ + triggerCapID: { + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: 0, + }, + targetCapID: { + LabelledName: "write-chain_evm_1", + Version: "1.0.0", + CapabilityType: 3, + }, + }, + IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + nodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[0], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + nodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[1], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + nodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[2], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + nodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: nodes[3], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + }, + }, + } + syncer := newRegistrySyncer(make(services.StopChan), wrapper, registry, dispatcher, lggr, HardcodedDonNetworkSetup{}, mr) + require.NoError(t, err) + + // If the DON were public, this would fail with two errors: + // - error fetching the capabilities from the registry since they haven't been added + // - erroneous calls to dispatcher.SetReceiver, since the call hasn't been registered. + err = syncer.sync(ctx) + require.NoError(t, err) + defer syncer.Close() + + // Finally, assert that no services were added. + assert.Len(t, syncer.subServices, 0) +} + +func TestSyncer_WiresUpClientsForPublicWorkflowDON(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + registry := NewRegistry(lggr) + dispatcher := remoteMocks.NewDispatcher(t) + + var pid ragetypes.PeerID + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) + require.NoError(t, err) + peer := mocks.NewPeer(t) + peer.On("UpdateConnections", mock.Anything).Return(nil) + peer.On("ID").Return(pid) + wrapper := mocks.NewPeerWrapper(t) + wrapper.On("GetPeer").Return(peer) + + workflowDonNodes := [][32]byte{ + pid, + randomWord(), + randomWord(), + randomWord(), + } + + capabilityDonNodes := [][32]byte{ + randomWord(), + randomWord(), + randomWord(), + randomWord(), + } + + fullTriggerCapID := "streams-trigger@1.0.0" + fullTargetID := "write-chain_evm_1@1.0.0" + triggerCapID := randomWord() + targetCapID := randomWord() + dID := uint32(1) + capDonID := uint32(2) + // The below state describes a Workflow DON (AcceptsWorkflows = true), + // which exposes the streams-trigger and write_chain capabilities. + // We expect receivers to be wired up and both capabilities to be added to the registry. + mr := &mockReader{ + s: state{ + IDsToDONs: map[donID]kcr.CapabilitiesRegistryDONInfo{ + donID(dID): { + Id: dID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + NodeP2PIds: workflowDonNodes, + }, + donID(capDonID): { + Id: capDonID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: false, + NodeP2PIds: capabilityDonNodes, + CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: triggerCapID, + Config: []byte(""), + }, + { + CapabilityId: targetCapID, + Config: []byte(""), + }, + }, + }, + }, + IDsToCapabilities: map[hashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ + triggerCapID: { + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: 0, + }, + targetCapID: { + LabelledName: "write-chain_evm_1", + Version: "1.0.0", + CapabilityType: 3, + }, + }, + IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + capabilityDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[0], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[1], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[2], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[3], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + workflowDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + }, + workflowDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + }, + workflowDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + }, + workflowDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + }, + }, + }, + } + syncer := newRegistrySyncer(make(services.StopChan), wrapper, registry, dispatcher, lggr, HardcodedDonNetworkSetup{}, mr) + require.NoError(t, err) + + dispatcher.On("SetReceiver", fullTriggerCapID, fmt.Sprint(capDonID), mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) + dispatcher.On("SetReceiver", fullTargetID, fmt.Sprint(capDonID), mock.AnythingOfType("*target.client")).Return(nil) + + err = syncer.sync(ctx) + require.NoError(t, err) + defer syncer.Close() + + _, err = registry.Get(ctx, fullTriggerCapID) + require.NoError(t, err) + + _, err = registry.Get(ctx, fullTargetID) + require.NoError(t, err) +} + +func TestSyncer_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilities(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + registry := NewRegistry(lggr) + dispatcher := remoteMocks.NewDispatcher(t) + + var pid ragetypes.PeerID + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) + require.NoError(t, err) + peer := mocks.NewPeer(t) + peer.On("UpdateConnections", mock.Anything).Return(nil) + peer.On("ID").Return(pid) + wrapper := mocks.NewPeerWrapper(t) + wrapper.On("GetPeer").Return(peer) + + workflowDonNodes := [][32]byte{ + pid, + randomWord(), + randomWord(), + randomWord(), + } + + capabilityDonNodes := [][32]byte{ + randomWord(), + randomWord(), + randomWord(), + randomWord(), + } + + fullTriggerCapID := "streams-trigger@1.0.0" + triggerCapID := randomWord() + targetCapID := randomWord() + dID := uint32(1) + triggerCapDonID := uint32(2) + targetCapDonID := uint32(3) + // The below state describes a Workflow DON (AcceptsWorkflows = true), + // which exposes the streams-trigger and write_chain capabilities. + // We expect receivers to be wired up and both capabilities to be added to the registry. + mr := &mockReader{ + s: state{ + IDsToDONs: map[donID]kcr.CapabilitiesRegistryDONInfo{ + donID(dID): { + Id: dID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + NodeP2PIds: workflowDonNodes, + }, + donID(triggerCapDonID): { + Id: triggerCapDonID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: false, + NodeP2PIds: capabilityDonNodes, + CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: triggerCapID, + Config: []byte(""), + }, + }, + }, + donID(targetCapDonID): { + Id: targetCapDonID, + ConfigCount: uint32(0), + F: uint8(1), + IsPublic: false, + AcceptsWorkflows: false, + NodeP2PIds: capabilityDonNodes, + CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: targetCapID, + Config: []byte(""), + }, + }, + }, + }, + IDsToCapabilities: map[hashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ + triggerCapID: { + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: 0, + }, + targetCapID: { + LabelledName: "write-chain_evm_1", + Version: "1.0.0", + CapabilityType: 3, + }, + }, + IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + capabilityDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[0], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[1], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[2], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + capabilityDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: capabilityDonNodes[3], + HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + }, + workflowDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + }, + workflowDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + }, + workflowDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + }, + workflowDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + }, + }, + }, + } + syncer := newRegistrySyncer(make(services.StopChan), wrapper, registry, dispatcher, lggr, HardcodedDonNetworkSetup{}, mr) + require.NoError(t, err) + + dispatcher.On("SetReceiver", fullTriggerCapID, fmt.Sprint(triggerCapDonID), mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) + + err = syncer.sync(ctx) + require.NoError(t, err) + defer syncer.Close() + + _, err = registry.Get(ctx, fullTriggerCapID) + require.NoError(t, err) +} diff --git a/core/capabilities/targets/mocks/chain_writer.go b/core/capabilities/targets/mocks/chain_writer.go index d8a5a677a1..8fe9a0585f 100644 --- a/core/capabilities/targets/mocks/chain_writer.go +++ b/core/capabilities/targets/mocks/chain_writer.go @@ -9,8 +9,6 @@ import ( mock "github.com/stretchr/testify/mock" types "github.com/smartcontractkit/chainlink-common/pkg/types" - - uuid "github.com/google/uuid" ) // ChainWriter is an autogenerated mock type for the ChainWriter type @@ -49,7 +47,7 @@ func (_m *ChainWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeCom } // GetTransactionStatus provides a mock function with given fields: ctx, transactionID -func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID uuid.UUID) (types.TransactionStatus, error) { +func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { ret := _m.Called(ctx, transactionID) if len(ret) == 0 { @@ -58,16 +56,16 @@ func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID u var r0 types.TransactionStatus var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID) (types.TransactionStatus, error)); ok { + 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, uuid.UUID) types.TransactionStatus); ok { + 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, uuid.UUID) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { r1 = rf(ctx, transactionID) } else { r1 = ret.Error(1) @@ -77,7 +75,7 @@ func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID u } // 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 interface{}, transactionID uuid.UUID, toAddress string, meta *types.TxMeta, value big.Int) error { +func (_m *ChainWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args interface{}, 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 { @@ -85,7 +83,7 @@ func (_m *ChainWriter) SubmitTransaction(ctx context.Context, contractName strin } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, interface{}, uuid.UUID, string, *types.TxMeta, big.Int) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, string, string, interface{}, string, string, *types.TxMeta, *big.Int) error); ok { r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) } else { r0 = ret.Error(0) diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 913551d20b..de65cb8519 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -95,8 +95,6 @@ func (cap *WriteTarget) Execute(ctx context.Context, request capabilities.Capabi cap.lggr.Debugw("Skipping empty report", "request", request) return success(), nil } - cap.lggr.Debugw("WriteTarget non-empty report - attempting to push to txmgr", "request", request, "reportLen", len(inputs.Report), "reportContextLen", len(inputs.Context), "nSignatures", len(inputs.Signatures)) - // TODO: validate encoded report is prefixed with workflowID and executionID that match the request meta rawExecutionID, err := hex.DecodeString(request.Metadata.WorkflowExecutionID) @@ -118,11 +116,12 @@ func (cap *WriteTarget) Execute(ctx context.Context, request capabilities.Capabi return nil, err } if transmitter != common.HexToAddress("0x0") { - // report already transmitted, early return + cap.lggr.Infow("WriteTarget report already onchain - returning without a tranmission attempt", "executionID", request.Metadata.WorkflowExecutionID) return success(), nil } - txID, err := uuid.NewUUID() // TODO(archseer): it seems odd that CW expects us to generate an ID, rather than return one + cap.lggr.Infow("WriteTarget non-empty report - attempting to push to txmgr", "request", request, "reportLen", len(inputs.Report), "reportContextLen", len(inputs.Context), "nSignatures", len(inputs.Signatures), "executionID", request.Metadata.WorkflowExecutionID) + txID, err := uuid.NewUUID() // NOTE: CW expects us to generate an ID, rather than return one if err != nil { return nil, err } @@ -131,10 +130,10 @@ func (cap *WriteTarget) Execute(ctx context.Context, request capabilities.Capabi // `nil` values, including for slices. Until the bug is fixed we need to ensure that there are no // `nil` values passed in the request. req := struct { - ReceiverAddress string - RawReport []byte - ReportContext []byte - Signatures [][]byte + Receiver string + RawReport []byte + ReportContext []byte + Signatures [][]byte }{reqConfig.Address, inputs.Report, inputs.Context, inputs.Signatures} if req.RawReport == nil { @@ -152,7 +151,7 @@ func (cap *WriteTarget) Execute(ctx context.Context, request capabilities.Capabi meta := commontypes.TxMeta{WorkflowExecutionID: &request.Metadata.WorkflowExecutionID} value := big.NewInt(0) - if err := cap.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID, cap.forwarderAddress, &meta, *value); err != nil { + if err := cap.cw.SubmitTransaction(ctx, "forwarder", "report", req, txID.String(), cap.forwarderAddress, &meta, value); err != nil { return nil, err } cap.lggr.Debugw("Transaction submitted", "request", request, "transaction", txID) diff --git a/core/capabilities/transmission/local_target_capability.go b/core/capabilities/transmission/local_target_capability.go index 4fddd93d40..c040e6ed43 100644 --- a/core/capabilities/transmission/local_target_capability.go +++ b/core/capabilities/transmission/local_target_capability.go @@ -7,7 +7,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/logger" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) // LocalTargetCapability handles the transmission protocol required for a target capability that exists in the same don as @@ -15,37 +14,34 @@ import ( type LocalTargetCapability struct { lggr logger.Logger capabilities.TargetCapability - peerID p2ptypes.PeerID - don capabilities.DON + localNode capabilities.Node } -func NewLocalTargetCapability(lggr logger.Logger, peerID p2ptypes.PeerID, don capabilities.DON, underlying capabilities.TargetCapability) *LocalTargetCapability { +func NewLocalTargetCapability(lggr logger.Logger, localDON capabilities.Node, underlying capabilities.TargetCapability) *LocalTargetCapability { return &LocalTargetCapability{ TargetCapability: underlying, lggr: lggr, - peerID: peerID, - don: don, + localNode: localDON, } } func (l *LocalTargetCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - if req.Config == nil || req.Config.Underlying["schedule"] == nil { - l.lggr.Debug("no schedule found, executing immediately") + if l.localNode.PeerID == nil || l.localNode.WorkflowDON.ID == "" { + l.lggr.Debugf("empty DON info, executing immediately") return l.TargetCapability.Execute(ctx, req) } - tc, err := ExtractTransmissionConfig(req.Config) - if err != nil { - return nil, fmt.Errorf("failed to extract transmission config from request config: %w", err) + if req.Config == nil || req.Config.Underlying["schedule"] == nil { + l.lggr.Debug("no schedule found, executing immediately") + return l.TargetCapability.Execute(ctx, req) } - peerIDToTransmissionDelay, err := GetPeerIDToTransmissionDelay(l.don.Members, l.don.Config.SharedSecret, - req.Metadata.WorkflowID+req.Metadata.WorkflowExecutionID, tc) + peerIDToTransmissionDelay, err := GetPeerIDToTransmissionDelay(l.localNode.WorkflowDON.Members, req) if err != nil { return nil, fmt.Errorf("failed to get peer ID to transmission delay map: %w", err) } - delay, existsForPeerID := peerIDToTransmissionDelay[l.peerID] + delay, existsForPeerID := peerIDToTransmissionDelay[*l.localNode.PeerID] if !existsForPeerID { return nil, nil } diff --git a/core/capabilities/transmission/local_target_capability_test.go b/core/capabilities/transmission/local_target_capability_test.go index 6b4d040f0f..ded4b5c30f 100644 --- a/core/capabilities/transmission/local_target_capability_test.go +++ b/core/capabilities/transmission/local_target_capability_test.go @@ -3,7 +3,6 @@ package transmission import ( "context" "crypto/rand" - "encoding/hex" "testing" "time" @@ -44,11 +43,6 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { }, ) - // The combination of this key and the metadata above - // will yield the permutation [3, 2, 0, 1] - key, err := hex.DecodeString("fb13ca015a9ec60089c7141e9522de79") - require.NoError(t, err) - testCases := []struct { name string position int @@ -67,7 +61,7 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { name: "position 1; oneAtATime", position: 1, schedule: "oneAtATime", - low: 200 * time.Millisecond, + low: 100 * time.Millisecond, high: 300 * time.Millisecond, }, { @@ -82,7 +76,7 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { position: 3, schedule: "oneAtATime", low: 100 * time.Millisecond, - high: 200 * time.Millisecond, + high: 300 * time.Millisecond, }, { name: "position 0; allAtOnce", @@ -128,7 +122,7 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { Config: m, Metadata: capabilities.RequestMetadata{ WorkflowID: "mock-workflow-id", - WorkflowExecutionID: "mock-execution-id", + WorkflowExecutionID: "mock-execution-id-1", }, } @@ -138,14 +132,14 @@ func TestScheduledExecutionStrategy_LocalDON(t *testing.T) { randKey(), randKey(), } - don := capabilities.DON{ - Members: ids, - Config: capabilities.DONConfig{ - SharedSecret: [16]byte(key), + localDON := capabilities.Node{ + WorkflowDON: capabilities.DON{ + ID: "1", + Members: ids, }, + PeerID: &ids[tc.position], } - peerID := ids[tc.position] - localTargetCapability := NewLocalTargetCapability(log, peerID, don, mt) + localTargetCapability := NewLocalTargetCapability(log, localDON, mt) _, err = localTargetCapability.Execute(tests.Context(t), req) diff --git a/core/capabilities/transmission/transmission.go b/core/capabilities/transmission/transmission.go index 5121a9bf9f..b41be5bcaa 100644 --- a/core/capabilities/transmission/transmission.go +++ b/core/capabilities/transmission/transmission.go @@ -4,13 +4,15 @@ import ( "fmt" "time" - "golang.org/x/crypto/sha3" + "github.com/pkg/errors" "github.com/smartcontractkit/libocr/permutation" - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + + "golang.org/x/crypto/sha3" ) var ( @@ -25,7 +27,7 @@ type TransmissionConfig struct { DeltaStage time.Duration } -func ExtractTransmissionConfig(config *values.Map) (TransmissionConfig, error) { +func extractTransmissionConfig(config *values.Map) (TransmissionConfig, error) { var tc struct { DeltaStage string Schedule string @@ -47,11 +49,21 @@ func ExtractTransmissionConfig(config *values.Map) (TransmissionConfig, error) { } // GetPeerIDToTransmissionDelay returns a map of PeerID to the time.Duration that the node with that PeerID should wait -// before transmitting. If a node is not in the map, it should not transmit. The sharedSecret is shared by nodes in the -// same DON and used to generate a deterministic schedule for the transmission delays. -func GetPeerIDToTransmissionDelay(donPeerIDs []ragep2ptypes.PeerID, sharedSecret [16]byte, transmissionID string, tc TransmissionConfig) (map[p2ptypes.PeerID]time.Duration, error) { +// before transmitting the capability request. If a node is not in the map, it should not transmit. +func GetPeerIDToTransmissionDelay(donPeerIDs []types.PeerID, req capabilities.CapabilityRequest) (map[types.PeerID]time.Duration, error) { + tc, err := extractTransmissionConfig(req.Config) + if err != nil { + return nil, fmt.Errorf("failed to extract transmission config from request: %w", err) + } + + if req.Metadata.WorkflowID == "" || req.Metadata.WorkflowExecutionID == "" { + return nil, errors.New("workflow ID and workflow execution ID must be set in request metadata") + } + + transmissionID := req.Metadata.WorkflowID + req.Metadata.WorkflowExecutionID + donMemberCount := len(donPeerIDs) - key := transmissionScheduleSeed(sharedSecret, transmissionID) + key := transmissionScheduleSeed(transmissionID) schedule, err := createTransmissionSchedule(tc.Schedule, donMemberCount) if err != nil { return nil, err @@ -59,7 +71,7 @@ func GetPeerIDToTransmissionDelay(donPeerIDs []ragep2ptypes.PeerID, sharedSecret picked := permutation.Permutation(donMemberCount, key) - peerIDToTransmissionDelay := map[p2ptypes.PeerID]time.Duration{} + peerIDToTransmissionDelay := map[types.PeerID]time.Duration{} for i, peerID := range donPeerIDs { delay := delayFor(i, schedule, picked, tc.DeltaStage) if delay != nil { @@ -96,11 +108,9 @@ func createTransmissionSchedule(scheduleType string, N int) ([]int, error) { return nil, fmt.Errorf("unknown schedule type %s", scheduleType) } -func transmissionScheduleSeed(sharedSecret [16]byte, transmissionID string) [16]byte { +func transmissionScheduleSeed(transmissionID string) [16]byte { hash := sha3.NewLegacyKeccak256() - hash.Write(sharedSecret[:]) hash.Write([]byte(transmissionID)) - var key [16]byte copy(key[:], hash.Sum(nil)) return key diff --git a/core/capabilities/transmission/transmission_test.go b/core/capabilities/transmission/transmission_test.go index bbdaaa27fe..fba233eadb 100644 --- a/core/capabilities/transmission/transmission_test.go +++ b/core/capabilities/transmission/transmission_test.go @@ -1,7 +1,6 @@ package transmission import ( - "encoding/hex" "fmt" "testing" "time" @@ -9,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -26,7 +26,6 @@ func Test_GetPeerIDToTransmissionDelay(t *testing.T) { testCases := []struct { name string peerName string - sharedSecret string schedule string deltaStage string workflowExecutionID string @@ -35,21 +34,19 @@ func Test_GetPeerIDToTransmissionDelay(t *testing.T) { { "TestOneAtATime", "one", - "fb13ca015a9ec60089c7141e9522de79", "oneAtATime", "100ms", "mock-execution-id", map[string]time.Duration{ "one": 300 * time.Millisecond, - "two": 200 * time.Millisecond, + "two": 100 * time.Millisecond, "three": 0 * time.Millisecond, - "four": 100 * time.Millisecond, + "four": 200 * time.Millisecond, }, }, { "TestAllAtOnce", "one", - "fb13ca015a9ec60089c7141e9522de79", "allAtOnce", "100ms", "mock-execution-id", @@ -63,33 +60,35 @@ func Test_GetPeerIDToTransmissionDelay(t *testing.T) { { "TestOneAtATimeWithDifferentExecutionID", "one", - "fb13ca015a9ec60089c7141e9522de79", "oneAtATime", "100ms", "mock-execution-id2", map[string]time.Duration{ "one": 0 * time.Millisecond, - "two": 300 * time.Millisecond, + "two": 200 * time.Millisecond, "three": 100 * time.Millisecond, - "four": 200 * time.Millisecond, + "four": 300 * time.Millisecond, }, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - sharedSecret, err := hex.DecodeString(tc.sharedSecret) - require.NoError(t, err) - - m, err := values.NewMap(map[string]any{ + transmissionCfg, err := values.NewMap(map[string]any{ "schedule": tc.schedule, "deltaStage": tc.deltaStage, }) require.NoError(t, err) - transmissionCfg, err := ExtractTransmissionConfig(m) - require.NoError(t, err) - peerIdToDelay, err := GetPeerIDToTransmissionDelay(ids, [16]byte(sharedSecret), "mock-workflow-id"+tc.workflowExecutionID, transmissionCfg) + capabilityRequest := capabilities.CapabilityRequest{ + Config: transmissionCfg, + Metadata: capabilities.RequestMetadata{ + WorkflowID: "mock-workflow-id", + WorkflowExecutionID: tc.workflowExecutionID, + }, + } + + peerIdToDelay, err := GetPeerIDToTransmissionDelay(ids, capabilityRequest) require.NoError(t, err) assert.Equal(t, tc.expectedDelays["one"], peerIdToDelay[peer1]) diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index f43b5189c7..22fac5f728 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + commontypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" ) @@ -60,7 +61,7 @@ const ( TransactionAlreadyMined Fatal ServiceUnavailable - OutOfCounters + TerminallyStuck ) type ClientErrors map[int]*regexp.Regexp @@ -246,10 +247,17 @@ var zkSync = ClientErrors{ } var zkEvm = ClientErrors{ - OutOfCounters: regexp.MustCompile(`(?:: |^)not enough .* counters to continue the execution$`), + TerminallyStuck: regexp.MustCompile(`(?:: |^)not enough .* counters to continue the execution$`), } -var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm} +const TerminallyStuckMsg = "transaction terminally stuck" + +// Tx.Error messages that are set internally so they are not chain or client specific +var internal = ClientErrors{ + TerminallyStuck: regexp.MustCompile(TerminallyStuckMsg), +} + +var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, internal} // ClientErrorRegexes returns a map of compiled regexes for each error type func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors { @@ -353,9 +361,16 @@ func (s *SendError) IsServiceUnavailable(configErrors *ClientErrors) bool { return s.is(ServiceUnavailable, configErrors) } -// IsOutOfCounters is a zk chain specific error returned if the transaction is too complex to prove on zk circuits -func (s *SendError) IsOutOfCounters(configErrors *ClientErrors) bool { - return s.is(OutOfCounters, configErrors) +// IsTerminallyStuck indicates if a transaction was stuck without any chance of inclusion +func (s *SendError) IsTerminallyStuckConfigError(configErrors *ClientErrors) bool { + return s.is(TerminallyStuck, configErrors) +} + +// IsFatal indicates if a transaction error is considered fatal for external callers +// The naming discrepancy is due to the generic transaction statuses introduced by ChainWriter +func (s *SendError) IsFatal() bool { + // An error classified as terminally stuck is considered fatal since the transaction payload should NOT be retried by external callers + return s.IsTerminallyStuckConfigError(nil) } // IsTimeout indicates if the error was caused by an exceeded context deadline @@ -399,6 +414,10 @@ func NewSendError(e error) *SendError { return &SendError{err: pkgerrors.WithStack(e), fatal: fatal} } +func NewTxError(e error) commontypes.ErrorClassifier { + return NewSendError(e) +} + // Geth/parity returns these errors if the transaction failed in such a way that: // 1. It will never be included into a block as a result of this send // 2. Resending the transaction at a different gas price will never change the outcome diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index 838eb96310..7dfd39f444 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -460,7 +460,7 @@ func (c *SimulatedBackendClient) EstimateGas(ctx context.Context, call ethereum. // SuggestGasPrice recommends a gas price. func (c *SimulatedBackendClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { - panic("unimplemented") + return c.b.SuggestGasPrice(ctx) } // BatchCallContext makes a batch rpc call. diff --git a/core/chains/evm/client/tx_simulator_test.go b/core/chains/evm/client/tx_simulator_test.go index ddd0a5fcff..d82db154e0 100644 --- a/core/chains/evm/client/tx_simulator_test.go +++ b/core/chains/evm/client/tx_simulator_test.go @@ -78,7 +78,7 @@ func TestSimulateTx_Default(t *testing.T) { Data: []byte("0x00"), } sendErr := client.SimulateTransaction(ctx, ethClient, logger.TestSugared(t), "", msg) - require.Equal(t, true, sendErr.IsOutOfCounters(nil)) + require.Equal(t, true, sendErr.IsTerminallyStuckConfigError(nil)) }) t.Run("returns without error if simulation returns non-OOC error", func(t *testing.T) { @@ -108,6 +108,6 @@ func TestSimulateTx_Default(t *testing.T) { Data: []byte("0x00"), } sendErr := client.SimulateTransaction(ctx, ethClient, logger.TestSugared(t), "", msg) - require.Equal(t, false, sendErr.IsOutOfCounters(nil)) + require.Equal(t, false, sendErr.IsTerminallyStuckConfigError(nil)) }) } diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index dd724a6689..d35f9bd0a3 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -380,10 +380,6 @@ func (c *Chain) ValidateConfig() (err error) { err = multierr.Append(err, commonconfig.ErrInvalid{Name: "GasEstimator.BumpTxDepth", Value: *c.GasEstimator.BumpTxDepth, Msg: "must be less than or equal to Transactions.MaxInFlight"}) } - if *c.HeadTracker.HistoryDepth < *c.FinalityDepth { - err = multierr.Append(err, commonconfig.ErrInvalid{Name: "HeadTracker.HistoryDepth", Value: *c.HeadTracker.HistoryDepth, - Msg: "must be equal to or greater than FinalityDepth"}) - } if *c.FinalityDepth < 1 { err = multierr.Append(err, commonconfig.ErrInvalid{Name: "FinalityDepth", Value: *c.FinalityDepth, Msg: "must be greater than or equal to 1"}) diff --git a/core/chains/evm/forwarders/forwarder_manager.go b/core/chains/evm/forwarders/forwarder_manager.go index 638836094d..3624cdf7a2 100644 --- a/core/chains/evm/forwarders/forwarder_manager.go +++ b/core/chains/evm/forwarders/forwarder_manager.go @@ -226,7 +226,7 @@ func (f *FwdMgr) initForwardersCache(ctx context.Context, fwdrs []Forwarder) { for _, fwdr := range fwdrs { senders, err := f.getAuthorizedSenders(ctx, fwdr.Address) if err != nil { - f.logger.Warnw("Failed to call getAuthorizedSenders on forwarder", fwdr, "err", err) + f.logger.Warnw("Failed to call getAuthorizedSenders on forwarder", "forwarder", fwdr.Address, "err", err) continue } f.setCachedSenders(fwdr.Address, senders) diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 12ccedb4b3..16a66e1c8b 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -2,6 +2,7 @@ package gas import ( "context" + "errors" "fmt" "math/big" "sort" @@ -11,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" - pkgerrors "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -40,21 +40,18 @@ var ( }, []string{"percentile", "evmChainID"}, ) - promBlockHistoryEstimatorAllTipCapPercentiles = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "gas_updater_all_tip_cap_percentiles", Help: "Tip cap at given percentile", }, []string{"percentile", "evmChainID"}, ) - promBlockHistoryEstimatorSetGasPrice = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "gas_updater_set_gas_price", Help: "Gas updater set gas price (in Wei)", }, []string{"percentile", "evmChainID"}, ) - promBlockHistoryEstimatorSetTipCap = promauto.NewGaugeVec(prometheus.GaugeOpts{ Name: "gas_updater_set_tip_cap", Help: "Gas updater set gas tip cap (in Wei)", @@ -111,12 +108,15 @@ type BlockHistoryEstimator struct { wg *sync.WaitGroup stopCh services.StopChan - gasPrice *assets.Wei - tipCap *assets.Wei - priceMu sync.RWMutex - latest *evmtypes.Head - latestMu sync.RWMutex - initialFetch atomic.Bool + gasPrice *assets.Wei + tipCap *assets.Wei + priceMu sync.RWMutex + maxPercentileGasPrice *assets.Wei + maxPercentileTipCap *assets.Wei + maxPriceMu sync.RWMutex + latest *evmtypes.Head + latestMu sync.RWMutex + initialFetch atomic.Bool logger logger.SugaredLogger @@ -174,15 +174,6 @@ func (b *BlockHistoryEstimator) getCurrentBaseFee() *assets.Wei { return b.latest.BaseFeePerGas } -func (b *BlockHistoryEstimator) getCurrentBlockNum() *int64 { - b.latestMu.RLock() - defer b.latestMu.RUnlock() - if b.latest == nil { - return nil - } - return &b.latest.Number -} - func (b *BlockHistoryEstimator) getBlocks() []evmtypes.Block { b.blocksMu.RLock() defer b.blocksMu.RUnlock() @@ -196,10 +187,10 @@ func (b *BlockHistoryEstimator) Start(ctx context.Context) error { b.logger.Trace("Starting") if b.bhConfig.CheckInclusionBlocks() > 0 { - b.logger.Infof("Inclusion checking enabled, bumping will be prevented on transactions that have been priced above the %d percentile for %d blocks", b.bhConfig.CheckInclusionPercentile(), b.bhConfig.CheckInclusionBlocks()) + b.logger.Infof("Inclusion checking enabled, bumping will be prevented on transactions that have been priced above the %d percentile of transactions in the latest %d blocks", b.bhConfig.CheckInclusionPercentile(), b.bhConfig.CheckInclusionBlocks()) } if b.bhConfig.BlockHistorySize() == 0 { - return pkgerrors.New("BlockHistorySize must be set to a value greater than 0") + return errors.New("BlockHistorySize must be set to a value greater than 0") } fetchCtx, cancel := context.WithTimeout(ctx, MaxStartTime) @@ -217,7 +208,7 @@ func (b *BlockHistoryEstimator) Start(ctx context.Context) error { // NOTE: This only checks the start context, not the fetch context if ctx.Err() != nil { - return pkgerrors.Wrap(ctx.Err(), "failed to start BlockHistoryEstimator due to main context error") + return fmt.Errorf("failed to start BlockHistoryEstimator due to main context error: %w", ctx.Err()) } b.wg.Add(1) @@ -252,11 +243,11 @@ func (b *BlockHistoryEstimator) GetLegacyGas(_ context.Context, _ []byte, gasLim gasPrice = b.getGasPrice() }) if !ok { - return nil, 0, pkgerrors.New("BlockHistoryEstimator is not started; cannot estimate gas") + return nil, 0, errors.New("BlockHistoryEstimator is not started; cannot estimate gas") } if gasPrice == nil { if !b.initialFetch.Load() { - return nil, 0, pkgerrors.New("BlockHistoryEstimator has not finished the first gas estimation yet, likely because a failure on start") + return nil, 0, errors.New("BlockHistoryEstimator has not finished the first gas estimation yet, likely because a failure on start") } b.logger.Warnw("Failed to estimate gas price. This is likely because there aren't any valid transactions to estimate from."+ "Using Evm.GasEstimator.PriceDefault as fallback.", "blocks", b.getBlockHistoryNumbers()) @@ -273,6 +264,18 @@ func (b *BlockHistoryEstimator) getGasPrice() *assets.Wei { return b.gasPrice } +func (b *BlockHistoryEstimator) getMaxPercentileGasPrice() *assets.Wei { + b.maxPriceMu.RLock() + defer b.maxPriceMu.RUnlock() + return b.maxPercentileGasPrice +} + +func (b *BlockHistoryEstimator) setMaxPercentileGasPrice(gasPrice *assets.Wei) { + b.maxPriceMu.Lock() + defer b.maxPriceMu.Unlock() + b.maxPercentileGasPrice = gasPrice +} + func (b *BlockHistoryEstimator) getBlockHistoryNumbers() (numsInHistory []int64) { for _, b := range b.blocks { numsInHistory = append(numsInHistory, b.Number) @@ -286,10 +289,22 @@ func (b *BlockHistoryEstimator) getTipCap() *assets.Wei { return b.tipCap } +func (b *BlockHistoryEstimator) getMaxPercentileTipCap() *assets.Wei { + b.maxPriceMu.RLock() + defer b.maxPriceMu.RUnlock() + return b.maxPercentileTipCap +} + +func (b *BlockHistoryEstimator) setMaxPercentileTipCap(tipCap *assets.Wei) { + b.maxPriceMu.Lock() + defer b.maxPriceMu.Unlock() + b.maxPercentileTipCap = tipCap +} + func (b *BlockHistoryEstimator) BumpLegacyGas(_ context.Context, originalGasPrice *assets.Wei, gasLimit uint64, maxGasPriceWei *assets.Wei, attempts []EvmPriorAttempt) (bumpedGasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { if b.bhConfig.CheckInclusionBlocks() > 0 { - if err = b.checkConnectivity(attempts); err != nil { - if pkgerrors.Is(err, commonfee.ErrConnectivity) { + if err = b.haltBumping(attempts); err != nil { + if errors.Is(err, commonfee.ErrConnectivity) { b.logger.Criticalw(BumpingHaltedLabel, "err", err) b.SvcErrBuffer.Append(err) promBlockHistoryEstimatorConnectivityFailureCount.WithLabelValues(b.chainID.String(), "legacy").Inc() @@ -304,76 +319,59 @@ func (b *BlockHistoryEstimator) BumpLegacyGas(_ context.Context, originalGasPric return bumpedGasPrice, gasLimit, err } -// checkConnectivity detects if the transaction is not being included due to -// some kind of mempool propagation or connectivity issue rather than -// insufficiently high pricing and returns error if so -func (b *BlockHistoryEstimator) checkConnectivity(attempts []EvmPriorAttempt) error { +// haltBumping prevents transactions from excessively bumping if an existing attempt's price is above a configurable percentile +// This check is required in case the transaction is not being included due to some kind of mempool propagation +// or connectivity issue rather than insufficiently high pricing +func (b *BlockHistoryEstimator) haltBumping(attempts []EvmPriorAttempt) error { percentile := int(b.bhConfig.CheckInclusionPercentile()) - // how many blocks since broadcast? - latestBlockNum := b.getCurrentBlockNum() - if latestBlockNum == nil { - b.logger.Warn("Latest block is unknown; skipping inclusion check") - // can't determine anything if we don't have/know latest block num yet - return nil + // Get latest CheckInclusionPercentile prices to use in the checks below + var maxGasPrice *assets.Wei + var maxTipCap *assets.Wei + ok := b.IfStarted(func() { + maxGasPrice = b.getMaxPercentileGasPrice() + maxTipCap = b.getMaxPercentileTipCap() + }) + if !ok { + return errors.New("BlockHistoryEstimator is not started; do not have max gas to allow bumping") } - expectInclusionWithinBlocks := int(b.bhConfig.CheckInclusionBlocks()) - blockHistory := b.getBlocks() - if len(blockHistory) < expectInclusionWithinBlocks { - b.logger.Warnf("Block history in memory with length %d is insufficient to determine whether transaction should have been included within the past %d blocks", len(blockHistory), b.bhConfig.CheckInclusionBlocks()) - return nil + if !b.initialFetch.Load() { + return errors.New("BlockHistoryEstimator has not finished the first gas estimation yet, likely because a failure on start") + } + // Return error to prevent bumping if gas price is nil or if EIP1559 is enabled and tip cap is nil + if maxGasPrice == nil || (b.eConfig.EIP1559DynamicFees() && maxTipCap == nil) { + errorMsg := fmt.Sprintf("%d percentile price is not set. This is likely because there aren't any valid transactions to estimate from. Preventing bumping until valid price is available to compare", percentile) + b.logger.Debugf(errorMsg) + return errors.New(errorMsg) } + // Get the latest CheckInclusionBlocks from block history for fee cap check below + blockHistory := b.getBlocks() + blockRange := mathutil.Min(len(blockHistory), int(b.bhConfig.CheckInclusionBlocks())) + startIdx := len(blockHistory) - blockRange + checkInclusionBlocks := blockHistory[startIdx:] + // Check each attempt for any with a gas price or tip cap (if EIP1559 type) exceeds the latest CheckInclusionPercentile prices for _, attempt := range attempts { if attempt.BroadcastBeforeBlockNum == nil { // this shouldn't happen; any broadcast attempt ought to have a // BroadcastBeforeBlockNum otherwise its an assumption violation - return pkgerrors.Errorf("BroadcastBeforeBlockNum was unexpectedly nil for attempt %s", attempt.TxHash) - } - broadcastBeforeBlockNum := *attempt.BroadcastBeforeBlockNum - blocksSinceBroadcast := *latestBlockNum - broadcastBeforeBlockNum - if blocksSinceBroadcast < int64(expectInclusionWithinBlocks) { - // only check attempts that have been waiting around longer than - // CheckInclusionBlocks - continue + return fmt.Errorf("BroadcastBeforeBlockNum was unexpectedly nil for attempt %s", attempt.TxHash) } - // has not been included for at least the required number of blocks - b.logger.Debugw(fmt.Sprintf("transaction %s has been pending inclusion for %d blocks which equals or exceeds expected specified check inclusion blocks of %d", attempt.TxHash, blocksSinceBroadcast, expectInclusionWithinBlocks), "broadcastBeforeBlockNum", broadcastBeforeBlockNum, "latestBlockNum", *latestBlockNum) - // is the price in the right percentile for all of these blocks? - var blocks []evmtypes.Block - l := expectInclusionWithinBlocks - // reverse order since we want to go highest -> lowest block number and bail out early - for i := l - 1; i >= 0; i-- { - block := blockHistory[i] - if block.Number < broadcastBeforeBlockNum { - break - } - blocks = append(blocks, block) - } - var eip1559 bool + var attemptEip1559 bool switch attempt.TxType { case 0x0, 0x1: - eip1559 = false + attemptEip1559 = false case 0x2: - eip1559 = true + attemptEip1559 = true default: - return pkgerrors.Errorf("attempt %s has unknown transaction type 0x%d", attempt.TxHash, attempt.TxType) + return fmt.Errorf("attempt %s has unknown transaction type 0x%d", attempt.TxHash, attempt.TxType) } - gasPrice, tipCap, err := b.calculatePercentilePrices(blocks, percentile, eip1559, nil, nil) - if err != nil { - if pkgerrors.Is(err, ErrNoSuitableTransactions) { - b.logger.Warnf("no suitable transactions found to verify if transaction %s has been included within expected inclusion blocks of %d", attempt.TxHash, expectInclusionWithinBlocks) - return nil - } - b.logger.AssumptionViolationw("unexpected error while verifying transaction inclusion", "err", err, "txHash", attempt.TxHash.String()) - return nil - } - if !eip1559 { - if attempt.GasPrice.Cmp(gasPrice) > 0 { - return pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction %s has gas price of %s, which is above percentile=%d%% (percentile price: %s) for blocks %d thru %d (checking %d blocks)", attempt.TxHash, attempt.GasPrice, percentile, gasPrice, blockHistory[l-1].Number, blockHistory[0].Number, expectInclusionWithinBlocks) + if !attemptEip1559 { + if attempt.GasPrice.Cmp(maxGasPrice) > 0 { + return fmt.Errorf("transaction %s has gas price of %s, which is above percentile=%d%% (percentile price: %s): %w", attempt.TxHash, attempt.GasPrice, percentile, maxGasPrice, commonfee.ErrConnectivity) } continue } sufficientFeeCap := true - for _, b := range blocks { + for _, b := range checkInclusionBlocks { // feecap must >= tipcap+basefee for the block, otherwise there // is no way this could have been included, and we must bail // out of the check @@ -384,8 +382,8 @@ func (b *BlockHistoryEstimator) checkConnectivity(attempts []EvmPriorAttempt) er break } } - if sufficientFeeCap && attempt.DynamicFee.TipCap.Cmp(tipCap) > 0 { - return pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction %s has tip cap of %s, which is above percentile=%d%% (percentile tip cap: %s) for blocks %d thru %d (checking %d blocks)", attempt.TxHash, attempt.DynamicFee.TipCap, percentile, tipCap, blockHistory[l-1].Number, blockHistory[0].Number, expectInclusionWithinBlocks) + if sufficientFeeCap && attempt.DynamicFee.TipCap.Cmp(maxTipCap) > 0 { + return fmt.Errorf("transaction %s has tip cap of %s, which is above percentile=%d%% (percentile tip cap: %s): %w", attempt.TxHash, attempt.DynamicFee.TipCap, percentile, maxTipCap, commonfee.ErrConnectivity) } } return nil @@ -393,7 +391,7 @@ func (b *BlockHistoryEstimator) checkConnectivity(attempts []EvmPriorAttempt) er func (b *BlockHistoryEstimator) GetDynamicFee(_ context.Context, maxGasPriceWei *assets.Wei) (fee DynamicFee, err error) { if !b.eConfig.EIP1559DynamicFees() { - return fee, pkgerrors.New("Can't get dynamic fee, EIP1559 is disabled") + return fee, errors.New("can't get dynamic fee, EIP1559 is disabled") } var feeCap *assets.Wei @@ -404,7 +402,7 @@ func (b *BlockHistoryEstimator) GetDynamicFee(_ context.Context, maxGasPriceWei tipCap = b.tipCap if tipCap == nil { if !b.initialFetch.Load() { - err = pkgerrors.New("BlockHistoryEstimator has not finished the first gas estimation yet, likely because a failure on start") + err = errors.New("BlockHistoryEstimator has not finished the first gas estimation yet, likely because a failure on start") return } b.logger.Warnw("Failed to estimate gas price. This is likely because there aren't any valid transactions to estimate from."+ @@ -425,12 +423,12 @@ func (b *BlockHistoryEstimator) GetDynamicFee(_ context.Context, maxGasPriceWei // This shouldn't happen on EIP-1559 blocks, since if the tip cap // is set, Start must have succeeded and we would expect an initial // base fee to be set as well - err = pkgerrors.New("BlockHistoryEstimator: no value for latest block base fee; cannot estimate EIP-1559 base fee. Are you trying to run with EIP1559 enabled on a non-EIP1559 chain?") + err = errors.New("BlockHistoryEstimator: no value for latest block base fee; cannot estimate EIP-1559 base fee. Are you trying to run with EIP1559 enabled on a non-EIP1559 chain?") return } }) if !ok { - return fee, pkgerrors.New("BlockHistoryEstimator is not started; cannot estimate gas") + return fee, errors.New("BlockHistoryEstimator is not started; cannot estimate gas") } if err != nil { return fee, err @@ -462,8 +460,8 @@ func calcFeeCap(latestAvailableBaseFeePerGas *assets.Wei, bufferBlocks int, tipC func (b *BlockHistoryEstimator) BumpDynamicFee(_ context.Context, originalFee DynamicFee, maxGasPriceWei *assets.Wei, attempts []EvmPriorAttempt) (bumped DynamicFee, err error) { if b.bhConfig.CheckInclusionBlocks() > 0 { - if err = b.checkConnectivity(attempts); err != nil { - if pkgerrors.Is(err, commonfee.ErrConnectivity) { + if err = b.haltBumping(attempts); err != nil { + if errors.Is(err, commonfee.ErrConnectivity) { b.logger.Criticalw(BumpingHaltedLabel, "err", err) b.SvcErrBuffer.Append(err) promBlockHistoryEstimatorConnectivityFailureCount.WithLabelValues(b.chainID.String(), "eip1559").Inc() @@ -506,8 +504,6 @@ func (b *BlockHistoryEstimator) FetchBlocksAndRecalculate(ctx context.Context, h // Recalculate adds the given heads to the history and recalculates gas price. func (b *BlockHistoryEstimator) Recalculate(head *evmtypes.Head) { - percentile := int(b.bhConfig.TransactionPercentile()) - lggr := b.logger.With("head", head) blockHistory := b.getBlocks() @@ -516,10 +512,21 @@ func (b *BlockHistoryEstimator) Recalculate(head *evmtypes.Head) { return } - l := mathutil.Min(len(blockHistory), int(b.bhConfig.BlockHistorySize())) - blocks := blockHistory[:l] + // Calculate and set the TransactionPercentile gas price and tip cap to use during gas estimation + b.calculateGasPriceTipCap(lggr, blockHistory, head) + + // Calculate and set the CheckInclusionPercentile gas price and tip cap to halt excessive bumping + b.calculateMaxPercentileGasPriceTipCap(lggr, blockHistory, head) +} +func (b *BlockHistoryEstimator) calculateGasPriceTipCap(lggr logger.SugaredLogger, blockHistory []evmtypes.Block, head *evmtypes.Head) { + percentile := int(b.bhConfig.TransactionPercentile()) eip1559 := b.eConfig.EIP1559DynamicFees() + + blockRange := mathutil.Min(len(blockHistory), int(b.bhConfig.BlockHistorySize())) + startIdx := len(blockHistory) - blockRange + blocks := blockHistory[startIdx:] + percentileGasPrice, percentileTipCap, err := b.calculatePercentilePrices(blocks, percentile, eip1559, func(gasPrices []*assets.Wei) { for i := 0; i <= 100; i += 5 { @@ -533,7 +540,7 @@ func (b *BlockHistoryEstimator) Recalculate(head *evmtypes.Head) { } }) if err != nil { - if pkgerrors.Is(err, ErrNoSuitableTransactions) { + if errors.Is(err, ErrNoSuitableTransactions) { lggr.Debug("No suitable transactions, skipping") } else { lggr.Warnw("Cannot calculate percentile prices", "err", err) @@ -541,32 +548,28 @@ func (b *BlockHistoryEstimator) Recalculate(head *evmtypes.Head) { return } - var numsInHistory []int64 - for _, b := range blockHistory { - numsInHistory = append(numsInHistory, b.Number) + var numsForPrice []int64 + for _, b := range blocks { + numsForPrice = append(numsForPrice, b.Number) } - float := new(big.Float).SetInt(percentileGasPrice.ToInt()) - gwei, _ := big.NewFloat(0).Quo(float, big.NewFloat(1000000000)).Float64() - gasPriceGwei := fmt.Sprintf("%.2f", gwei) - + gasPriceGwei := percentileGasPrice.Text("gwei") lggrFields := []interface{}{ "gasPriceWei", percentileGasPrice, "gasPriceGWei", gasPriceGwei, "maxGasPriceWei", b.eConfig.PriceMax(), "headNum", head.Number, - "blocks", numsInHistory, + "priceBlocks", numsForPrice, } b.setPercentileGasPrice(percentileGasPrice) promBlockHistoryEstimatorSetGasPrice.WithLabelValues(fmt.Sprintf("%v%%", percentile), b.chainID.String()).Set(float64(percentileGasPrice.Int64())) if !eip1559 { - lggr.Debugw(fmt.Sprintf("Setting new default gas price: %v Gwei", gasPriceGwei), lggrFields...) + lggr.Debugw(fmt.Sprintf("Setting new default GasPrice: %v Gwei", gasPriceGwei), lggrFields...) return } - float = new(big.Float).SetInt(percentileTipCap.ToInt()) - gwei, _ = big.NewFloat(0).Quo(float, big.NewFloat(1000000000)).Float64() - tipCapGwei := fmt.Sprintf("%.2f", gwei) + + tipCapGwei := percentileTipCap.Text("gwei") lggrFields = append(lggrFields, []interface{}{ "tipCapWei", percentileTipCap, "tipCapGwei", tipCapGwei, @@ -576,6 +579,56 @@ func (b *BlockHistoryEstimator) Recalculate(head *evmtypes.Head) { promBlockHistoryEstimatorSetTipCap.WithLabelValues(fmt.Sprintf("%v%%", percentile), b.chainID.String()).Set(float64(percentileTipCap.Int64())) } +func (b *BlockHistoryEstimator) calculateMaxPercentileGasPriceTipCap(lggr logger.SugaredLogger, blockHistory []evmtypes.Block, head *evmtypes.Head) { + if b.bhConfig.CheckInclusionBlocks() <= 0 { + return + } + percentile := int(b.bhConfig.CheckInclusionPercentile()) + eip1559 := b.eConfig.EIP1559DynamicFees() + + blockRange := mathutil.Min(len(blockHistory), int(b.bhConfig.CheckInclusionBlocks())) + startIdx := len(blockHistory) - blockRange + checkInclusionBlocks := blockHistory[startIdx:] + + maxPercentileGasPrice, maxPercentileTipCap, err := b.calculatePercentilePrices(checkInclusionBlocks, percentile, eip1559, nil, nil) + if err != nil { + if errors.Is(err, ErrNoSuitableTransactions) { + lggr.Debug("No suitable transactions found to calculate the max percentile prices, skipping") + } else { + lggr.Warnw("Cannot calculate max percentile prices", "err", err) + } + return + } + + var numsForMaxPrices []int64 + for _, b := range checkInclusionBlocks { + numsForMaxPrices = append(numsForMaxPrices, b.Number) + } + + maxPercentileGasPriceGwei := maxPercentileGasPrice.Text("gwei") + lggrFields := []interface{}{ + "maxPercentileGasPriceWei", maxPercentileGasPrice, + "maxPercentileGasPriceGwei", maxPercentileGasPriceGwei, + "headNum", head.Number, + "maxPercentileBlocks", numsForMaxPrices, + } + + b.setMaxPercentileGasPrice(maxPercentileGasPrice) + + if !eip1559 { + lggr.Debugw(fmt.Sprintf("Setting new max percentile GasPrice: %v Gwei", maxPercentileGasPriceGwei), lggrFields...) + return + } + + maxPercentileTipCapGwei := maxPercentileTipCap.Text("gwei") + lggrFields = append(lggrFields, []interface{}{ + "maxPercentileTipCapWei", maxPercentileTipCap, + "maxPercentileTipCapGwei", maxPercentileTipCapGwei, + }...) + lggr.Debugw(fmt.Sprintf("Setting new default prices, max percentile GasPrice: %v Gwei, max percentile TipCap: %v Gwei", maxPercentileGasPriceGwei, maxPercentileTipCapGwei), lggrFields...) + b.setMaxPercentileTipCap(maxPercentileTipCap) +} + // FetchBlocks fetches block history leading up to the given head. func (b *BlockHistoryEstimator) FetchBlocks(ctx context.Context, head *evmtypes.Head) error { // HACK: blockDelay is the number of blocks that the block history estimator trails behind head. @@ -588,12 +641,12 @@ func (b *BlockHistoryEstimator) FetchBlocks(ctx context.Context, head *evmtypes. historySize := b.size if historySize <= 0 { - return pkgerrors.Errorf("BlockHistoryEstimator: history size must be > 0, got: %d", historySize) + return fmt.Errorf("BlockHistoryEstimator: history size must be > 0, got: %d", historySize) } highestBlockToFetch := head.Number - blockDelay if highestBlockToFetch < 0 { - return pkgerrors.Errorf("BlockHistoryEstimator: cannot fetch, current block height %v is lower than EVM.RPCBlockQueryDelay=%v", head.Number, blockDelay) + return fmt.Errorf("BlockHistoryEstimator: cannot fetch, current block height %v is lower than EVM.RPCBlockQueryDelay=%v", head.Number, blockDelay) } lowestBlockToFetch := head.Number - historySize - blockDelay + 1 if lowestBlockToFetch < 0 { @@ -641,7 +694,7 @@ func (b *BlockHistoryEstimator) FetchBlocks(ctx context.Context, head *evmtypes. for _, req := range reqs { result, err := req.Result, req.Error if err != nil { - if pkgerrors.Is(err, evmtypes.ErrMissingBlock) { + if errors.Is(err, evmtypes.ErrMissingBlock) { num := HexToInt64(req.Args[0]) missingBlocks = append(missingBlocks, num) lggr.Debugw( @@ -657,10 +710,10 @@ func (b *BlockHistoryEstimator) FetchBlocks(ctx context.Context, head *evmtypes. block, is := result.(*evmtypes.Block) if !is { - return pkgerrors.Errorf("expected result to be a %T, got %T", &evmtypes.Block{}, result) + return fmt.Errorf("expected result to be a %T, got %T", &evmtypes.Block{}, result) } if block == nil { - return pkgerrors.New("invariant violation: got nil block") + return errors.New("invariant violation: got nil block") } if block.Hash == (common.Hash{}) { lggr.Warnw("Block was missing hash", "block", b, "headNum", head.Number, "blockNum", block.Number) @@ -716,26 +769,26 @@ func (b *BlockHistoryEstimator) batchFetch(ctx context.Context, reqs []rpc.Batch b.logger.Tracew(fmt.Sprintf("Batch fetching blocks %v thru %v", HexToInt64(reqs[i].Args[0]), HexToInt64(reqs[j-1].Args[0]))) err := b.ethClient.BatchCallContext(ctx, reqs[i:j]) - if pkgerrors.Is(err, context.DeadlineExceeded) { + if errors.Is(err, context.DeadlineExceeded) { // We ran out of time, return what we have b.logger.Warnf("Batch fetching timed out; loaded %d/%d results: %v", i, len(reqs), err) for k := i; k < len(reqs); k++ { if k < j { - reqs[k].Error = pkgerrors.Wrap(err, "request failed") + reqs[k].Error = fmt.Errorf("request failed: %w", err) } else { - reqs[k].Error = pkgerrors.Wrap(err, "request skipped; previous request exceeded deadline") + reqs[k].Error = fmt.Errorf("request skipped; previous request exceeded deadline: %w", err) } } return nil } else if err != nil { - return pkgerrors.Wrap(err, "BlockHistoryEstimator#fetchBlocks error fetching blocks with BatchCallContext") + return fmt.Errorf("BlockHistoryEstimator#fetchBlocks error fetching blocks with BatchCallContext: %w", err) } } return nil } var ( - ErrNoSuitableTransactions = pkgerrors.New("no suitable transactions") + ErrNoSuitableTransactions = errors.New("no suitable transactions") ) func (b *BlockHistoryEstimator) calculatePercentilePrices(blocks []evmtypes.Block, percentile int, eip1559 bool, f func(gasPrices []*assets.Wei), f2 func(tipCaps []*assets.Wei)) (gasPrice, tipCap *assets.Wei, err error) { @@ -796,7 +849,7 @@ func (b *BlockHistoryEstimator) getPricesFromBlocks(blocks []evmtypes.Block, eip func verifyBlock(block evmtypes.Block, eip1559 bool) error { if eip1559 && block.BaseFeePerGas == nil { - return pkgerrors.New("EIP-1559 mode was enabled, but block was missing baseFeePerGas") + return errors.New("EIP-1559 mode was enabled, but block was missing baseFeePerGas") } return nil } @@ -896,8 +949,7 @@ func (b *BlockHistoryEstimator) getEffectiveGasPrice(block evmtypes.Block, tx ev priorityFeePerGas = maxFeeMinusBaseFee } - effectiveGasPrice := priorityFeePerGas.Add(block.BaseFeePerGas) - return effectiveGasPrice + return priorityFeePerGas.Add(block.BaseFeePerGas) } func (b *BlockHistoryEstimator) EffectiveTipCap(block evmtypes.Block, tx evmtypes.Transaction) *assets.Wei { diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index d40e847036..06f9ae86e8 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -722,6 +722,9 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_NoEIP1559(t *testing.T) bhCfg.TransactionPercentileF = uint16(35) bhCfg.BlockHistorySizeF = uint16(3) bhCfg.BatchSizeF = uint32(0) + // Set CheckInclusionBlocks larger than BlockHistorySize to cache more blocks than needed for calculation + // Helps test whether the latest block is being used or not + bhCfg.CheckInclusionBlocksF = uint16(5) geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false @@ -730,39 +733,116 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_NoEIP1559(t *testing.T) bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + b0 := evmtypes.Block{ + Number: 0, + Hash: utils.NewHash(), + Transactions: legacyTransactionsFromGasPrices(1, 2, 3), + } b1 := evmtypes.Block{ Number: 1, Hash: utils.NewHash(), - Transactions: legacyTransactionsFromGasPrices(1), + Transactions: legacyTransactionsFromGasPrices(4, 5, 6), } b2 := evmtypes.Block{ Number: 2, Hash: utils.NewHash(), - Transactions: legacyTransactionsFromGasPrices(2), + Transactions: legacyTransactionsFromGasPrices(7, 8, 9), } b3 := evmtypes.Block{ Number: 3, Hash: utils.NewHash(), + Transactions: legacyTransactionsFromGasPrices(100), + } + b4 := evmtypes.Block{ + Number: 4, + Hash: utils.NewHash(), Transactions: legacyTransactionsFromGasPrices(200, 300, 100, 100, 100, 100), } ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 3 && - b[0].Args[0] == "0x3" && - b[1].Args[0] == "0x2" && - b[2].Args[0] == "0x1" + return len(b) == 5 && + b[0].Args[0] == "0x4" && + b[1].Args[0] == "0x3" && + b[2].Args[0] == "0x2" && + b[3].Args[0] == "0x1" && + b[4].Args[0] == "0x0" })).Return(nil).Run(func(args mock.Arguments) { elems := args.Get(1).([]rpc.BatchElem) - elems[0].Result = &b3 - elems[1].Result = &b2 - elems[2].Result = &b1 + elems[0].Result = &b4 + elems[1].Result = &b3 + elems[2].Result = &b2 + elems[3].Result = &b1 + elems[4].Result = &b0 }) - bhe.FetchBlocksAndRecalculate(tests.Context(t), testutils.Head(3)) + bhe.FetchBlocksAndRecalculate(tests.Context(t), testutils.Head(4)) price := gas.GetGasPrice(bhe) require.Equal(t, assets.NewWeiI(100), price) + assert.Len(t, gas.GetRollingBlockHistory(bhe), 5) +} + +func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_EIP1559(t *testing.T) { + t.Parallel() + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + cfg := gas.NewMockConfig() + bhCfg := newBlockHistoryConfig() + bhCfg.BlockDelayF = uint16(0) + bhCfg.TransactionPercentileF = uint16(50) + bhCfg.BlockHistorySizeF = uint16(1) + bhCfg.BatchSizeF = uint32(0) + // Set CheckInclusionBlocks larger than BlockHistorySize to cache more blocks than needed for calculation + // Helps test whether the latest block is being used or not + bhCfg.CheckInclusionBlocksF = uint16(3) + + geCfg := &gas.MockGasEstimatorConfig{} + geCfg.EIP1559DynamicFeesF = true + geCfg.PriceMaxF = assets.NewWeiI(1000) + geCfg.PriceMinF = assets.NewWeiI(0) + geCfg.TipCapMinF = assets.NewWeiI(0) + + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + + b0 := evmtypes.Block{ + BaseFeePerGas: assets.NewWeiI(1), + Number: 0, + Hash: utils.NewHash(), + Transactions: dynamicFeeTransactionsFromTipCaps(1, 2, 3), + } + b1 := evmtypes.Block{ + BaseFeePerGas: assets.NewWeiI(2), + Number: 1, + Hash: utils.NewHash(), + Transactions: dynamicFeeTransactionsFromTipCaps(4, 5, 6), + } + b2 := evmtypes.Block{ + BaseFeePerGas: assets.NewWeiI(3), + Number: 2, + Hash: utils.NewHash(), + Transactions: dynamicFeeTransactionsFromTipCaps(7, 8, 9), + } + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 3 && + b[0].Args[0] == "0x2" && + b[1].Args[0] == "0x1" && + b[2].Args[0] == "0x0" + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &b2 + elems[1].Result = &b1 + elems[2].Result = &b0 + }) + + bhe.FetchBlocksAndRecalculate(tests.Context(t), testutils.Head(2)) + + price := gas.GetTipCap(bhe) + require.Equal(t, assets.NewWeiI(8), price) // 50th percentile of latest block + assert.Len(t, gas.GetRollingBlockHistory(bhe), 3) } @@ -2132,78 +2212,82 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { }) } -func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { +func TestBlockHistoryEstimator_HaltBumping(t *testing.T) { cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.CheckInclusionBlocksF = uint16(4) - lggr, obs := logger.TestObserved(t, zapcore.DebugLevel) + bhCfg.CheckInclusionPercentileF = uint16(90) + lggr, _ := logger.TestObserved(t, zapcore.DebugLevel) geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false + geCfg.PriceMinF = assets.NewWeiI(1) + geCfg.PriceMaxF = assets.NewWeiI(100) l1Oracle := rollupMocks.NewL1Oracle(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) bhe := gas.BlockHistoryEstimatorFromInterface( - gas.NewBlockHistoryEstimator(lggr, nil, cfg, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), + gas.NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), ) attempts := []gas.EvmPriorAttempt{ {TxType: 0x0, TxHash: NewEvmHash()}, } - t.Run("skips connectivity check if latest block is not present", func(t *testing.T) { - err := bhe.CheckConnectivity(attempts) - require.NoError(t, err) - - tests.AssertLogEventually(t, obs, "Latest block is unknown; skipping inclusion check") + t.Run("fails halt bumping check if estimator is not started", func(t *testing.T) { + err := bhe.HaltBumping(attempts) + require.Error(t, err, "BlockHistoryEstimator is not started; do not have max gas to allow bumping") }) - h := testutils.Head(1) - h.BaseFeePerGas = assets.NewWeiI(112500) - bhe.OnNewLongestChain(tests.Context(t), h) - + h := testutils.Head(0) b0 := evmtypes.Block{ Number: 0, Hash: utils.NewHash(), Transactions: legacyTransactionsFromGasPrices(), } - gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b0}) - - t.Run("skips connectivity check if block history has insufficient size", func(t *testing.T) { - err := bhe.CheckConnectivity(attempts) - require.NoError(t, err) - - tests.AssertLogEventually(t, obs, "Block history in memory with length 1 is insufficient to determine whether transaction should have been included within the past 4 blocks") - }) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &b0 + }).Once() + err := bhe.Start(ctx) + require.NoError(t, err) - t.Run("skips connectivity check if attempts is nil or empty", func(t *testing.T) { - err := bhe.CheckConnectivity(nil) - require.NoError(t, err) + t.Run("allows bumping check if CheckInclusionPercentile price failed to set due to no suitable transactions", func(t *testing.T) { + err := bhe.HaltBumping(attempts) + require.Error(t, err, "90 percentile price is not set. This is likely because there aren't any valid transactions to estimate from. Preventing bumping until valid price is available to compare") }) b1 := evmtypes.Block{ Number: 1, Hash: utils.NewHash(), ParentHash: b0.Hash, - Transactions: legacyTransactionsFromGasPrices(), + Transactions: legacyTransactionsFromGasPrices(10, 20, 30, 40, 50), } b2 := evmtypes.Block{ Number: 2, Hash: utils.NewHash(), ParentHash: b1.Hash, - Transactions: legacyTransactionsFromGasPrices(), + Transactions: legacyTransactionsFromGasPrices(60, 70, 80), } b3 := evmtypes.Block{ Number: 3, Hash: utils.NewHash(), ParentHash: b2.Hash, - Transactions: legacyTransactionsFromGasPrices(), + Transactions: legacyTransactionsFromGasPrices(90, 100), } gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b0, b1, b2, b3}) - h = testutils.Head(5) - h.BaseFeePerGas = assets.NewWeiI(112500) - bhe.OnNewLongestChain(tests.Context(t), h) + bhe.Recalculate(testutils.Head(3)) + + t.Run("skips halt bumping check if attempts is nil or empty", func(t *testing.T) { + err := bhe.HaltBumping(nil) + require.NoError(t, err) + }) t.Run("returns error if one of the supplied attempts is missing BroadcastBeforeBlockNum", func(t *testing.T) { - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("BroadcastBeforeBlockNum was unexpectedly nil for attempt %s", attempts[0].TxHash)) }) @@ -2215,7 +2299,7 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { } t.Run("returns error if one of the supplied attempts has an unknown transaction type", func(t *testing.T) { - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.Error(t, err) assert.Contains(t, err.Error(), fmt.Sprintf("attempt %s has unknown transaction type 0x3", hash)) }) @@ -2224,13 +2308,6 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { {TxType: 0x0, BroadcastBeforeBlockNum: &num, TxHash: hash}, } - t.Run("skips connectivity check if no transactions are suitable", func(t *testing.T) { - err := bhe.CheckConnectivity(attempts) - require.NoError(t, err) - - tests.AssertLogEventually(t, obs, fmt.Sprintf("no suitable transactions found to verify if transaction %s has been included within expected inclusion blocks of 4", hash)) - }) - t.Run("in legacy mode", func(t *testing.T) { b0 = evmtypes.Block{ Number: 0, @@ -2258,43 +2335,27 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b0, b1, b2, b3}) attempts = []gas.EvmPriorAttempt{ - {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(1000), BroadcastBeforeBlockNum: ptr(int64(4))}, // This is very expensive but will be ignored due to BroadcastBeforeBlockNum being too recent {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(3), BroadcastBeforeBlockNum: ptr(int64(0))}, {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(5), BroadcastBeforeBlockNum: ptr(int64(1))}, {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(7), BroadcastBeforeBlockNum: ptr(int64(1))}, } - t.Run("passes check if all blocks have percentile price higher or exactly at the highest transaction gas price", func(t *testing.T) { + t.Run("passes check if all attempt gas prices are lower than or equal to percentile price", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 3 bhCfg.CheckInclusionPercentileF = 80 // percentile price is 7 wei + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.NoError(t, err) }) - t.Run("fails check if one or more blocks has percentile price higher than highest transaction gas price", func(t *testing.T) { + t.Run("fails check if any attempt price is higher than percentile price", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 3 bhCfg.CheckInclusionPercentileF = 40 // percentile price is 5 wei + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 7 wei, which is above percentile=40%% (percentile price: 5 wei) for blocks 2 thru 0 (checking 3 blocks)", attempts[3].TxHash)) - require.ErrorIs(t, err, commonfee.ErrConnectivity) - }) - - t.Run("fails check if one or more blocks has percentile price higher than any transaction gas price", func(t *testing.T) { - bhCfg.CheckInclusionBlocksF = 3 - bhCfg.CheckInclusionPercentileF = 30 // percentile price is 4 wei - - err := bhe.CheckConnectivity(attempts) - require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 5 wei, which is above percentile=30%% (percentile price: 4 wei) for blocks 2 thru 0 (checking 3 blocks)", attempts[2].TxHash)) - - bhCfg.CheckInclusionBlocksF = 3 - bhCfg.CheckInclusionPercentileF = 5 // percentile price is 2 wei - - err = bhe.CheckConnectivity(attempts) - require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 3 wei, which is above percentile=5%% (percentile price: 2 wei) for blocks 2 thru 0 (checking 3 blocks)", attempts[1].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 7 wei, which is above percentile=40%% (percentile price: 5 wei)", attempts[2].TxHash)) require.ErrorIs(t, err, commonfee.ErrConnectivity) }) }) @@ -2316,17 +2377,19 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { t.Run("passes check if both transactions are ok", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 1 bhCfg.CheckInclusionPercentileF = 90 // percentile price is 5 wei + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.NoError(t, err) }) t.Run("fails check if legacy transaction fails", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 1 bhCfg.CheckInclusionPercentileF = 60 + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 10 wei, which is above percentile=60%% (percentile price: 7 wei) for blocks 3 thru 3 (checking 1 blocks)", attempts[1].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 10 wei, which is above percentile=60%% (percentile price: 7 wei)", attempts[1].TxHash)) require.ErrorIs(t, err, commonfee.ErrConnectivity) }) @@ -2336,18 +2399,21 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { } t.Run("fails check if dynamic fee transaction fails", func(t *testing.T) { - gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b0}) + geCfg.EIP1559DynamicFeesF = true + geCfg.TipCapMinF = assets.NewWeiI(1) bhCfg.CheckInclusionBlocksF = 1 bhCfg.CheckInclusionPercentileF = 60 + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 10 wei, which is above percentile=60%% (percentile tip cap: 6 wei) for blocks 3 thru 3 (checking 1 blocks)", attempts[0].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 10 wei, which is above percentile=60%% (percentile tip cap: 6 wei)", attempts[0].TxHash)) require.ErrorIs(t, err, commonfee.ErrConnectivity) }) }) t.Run("in EIP-1559 mode", func(t *testing.T) { + geCfg.EIP1559DynamicFeesF = true b0 = evmtypes.Block{ BaseFeePerGas: assets.NewWeiI(5), Number: 0, @@ -2379,47 +2445,50 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { gas.SetRollingBlockHistory(bhe, blocks) attempts = []gas.EvmPriorAttempt{ - {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(1000)}, BroadcastBeforeBlockNum: ptr(int64(4))}, // This is very expensive but will be ignored due to BroadcastBeforeBlockNum being too recent {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(3)}, BroadcastBeforeBlockNum: ptr(int64(0))}, {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(5)}, BroadcastBeforeBlockNum: ptr(int64(1))}, {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(30), TipCap: assets.NewWeiI(7)}, BroadcastBeforeBlockNum: ptr(int64(1))}, } - t.Run("passes check if all blocks have 90th percentile price higher than highest transaction tip cap", func(t *testing.T) { + t.Run("passes check if 90th percentile price higher than highest transaction tip cap", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 3 bhCfg.CheckInclusionPercentileF = 80 + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.NoError(t, err) }) - t.Run("fails check if one or more blocks has percentile tip cap higher than any transaction tip cap, and base fee higher than the block base fee", func(t *testing.T) { + t.Run("fails check if percentile tip cap higher than any transaction tip cap, and base fee higher than the block base fee", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 3 bhCfg.CheckInclusionPercentileF = 20 + bhe.Recalculate(testutils.Head(3)) - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 5 wei, which is above percentile=20%% (percentile tip cap: 4 wei) for blocks 2 thru 0 (checking 3 blocks)", attempts[2].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 5 wei, which is above percentile=20%% (percentile tip cap: 4 wei)", attempts[1].TxHash)) require.ErrorIs(t, err, commonfee.ErrConnectivity) bhCfg.CheckInclusionBlocksF = 3 - bhCfg.CheckInclusionPercentileF = 5 + bhCfg.CheckInclusionPercentileF = 2 + bhe.Recalculate(testutils.Head(3)) - err = bhe.CheckConnectivity(attempts) + err = bhe.HaltBumping(attempts) require.Error(t, err) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 3 wei, which is above percentile=5%% (percentile tip cap: 2 wei) for blocks 2 thru 0 (checking 3 blocks)", attempts[1].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 3 wei, which is above percentile=2%% (percentile tip cap: 2 wei)", attempts[0].TxHash)) require.ErrorIs(t, err, commonfee.ErrConnectivity) }) t.Run("passes check if, for at least one block, feecap < tipcap+basefee, even if percentile is not reached", func(t *testing.T) { bhCfg.CheckInclusionBlocksF = 3 bhCfg.CheckInclusionPercentileF = 5 + bhe.Recalculate(testutils.Head(3)) attempts = []gas.EvmPriorAttempt{ {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{FeeCap: assets.NewWeiI(4), TipCap: assets.NewWeiI(7)}, BroadcastBeforeBlockNum: ptr(int64(1))}, } - err := bhe.CheckConnectivity(attempts) + err := bhe.HaltBumping(attempts) require.NoError(t, err) }) }) @@ -2430,8 +2499,9 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { maxGasPrice := assets.NewWeiI(1000000) bhCfg := newBlockHistoryConfig() - t.Run("BumpLegacyGas checks connectivity", func(t *testing.T) { + t.Run("BumpLegacyGas halts bumping", func(t *testing.T) { cfg := gas.NewMockConfig() + bhCfg.BlockDelayF = 0 bhCfg.CheckInclusionBlocksF = 1 bhCfg.CheckInclusionPercentileF = 10 geCfg := &gas.MockGasEstimatorConfig{} @@ -2439,39 +2509,57 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.BumpPercentF = 10 geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice + geCfg.PriceMinF = assets.NewWeiI(0) l1Oracle := rollupMocks.NewL1Oracle(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe := gas.BlockHistoryEstimatorFromInterface( + gas.NewBlockHistoryEstimator(logger.Test(t), ethClient, cfg, geCfg, bhCfg, testutils.NewRandomEVMChainID(), l1Oracle), + ) - b1 := evmtypes.Block{ - Number: 1, + b0 := evmtypes.Block{ + Number: 0, Hash: utils.NewHash(), Transactions: legacyTransactionsFromGasPrices(1), } - gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b1}) - head := testutils.Head(1) - bhe.OnNewLongestChain(tests.Context(t), head) + h := testutils.Head(0) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil).Once() + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &b0 + }).Once() + err := bhe.Start(ctx) + require.NoError(t, err) attempts := []gas.EvmPriorAttempt{ {TxType: 0x0, TxHash: NewEvmHash(), GasPrice: assets.NewWeiI(1000), BroadcastBeforeBlockNum: ptr(int64(0))}, } - - _, _, err := bhe.BumpLegacyGas(tests.Context(t), assets.NewWeiI(42), 100000, maxGasPrice, attempts) + _, _, err = bhe.BumpLegacyGas(ctx, assets.NewWeiI(42), 100000, maxGasPrice, attempts) require.Error(t, err) assert.True(t, pkgerrors.Is(err, commonfee.ErrConnectivity)) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 1 kwei, which is above percentile=10%% (percentile price: 1 wei) for blocks 1 thru 1 (checking 1 blocks)", attempts[0].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has gas price of 1 kwei, which is above percentile=10%% (percentile price: 1 wei)", attempts[0].TxHash)) }) t.Run("BumpLegacyGas calls BumpLegacyGasPriceOnly with proper current gas price", func(t *testing.T) { cfg := gas.NewMockConfig() + bhCfg := newBlockHistoryConfig() + bhCfg.CheckInclusionBlocksF = 0 geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false geCfg.BumpPercentF = 10 geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice l1Oracle := rollupMocks.NewL1Oracle(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil).Once() + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + err := bhe.Start(ctx) + require.NoError(t, err) t.Run("ignores nil current gas price", func(t *testing.T) { gasPrice, gasLimit, err := bhe.BumpLegacyGas(tests.Context(t), assets.NewWeiI(42), 100000, maxGasPrice, nil) @@ -2551,28 +2639,38 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.BumpPercentF = 10 geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice + geCfg.PriceMinF = assets.NewWeiI(0) + geCfg.TipCapMinF = assets.NewWeiI(0) l1Oracle := rollupMocks.NewL1Oracle(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) - b1 := evmtypes.Block{ + b0 := evmtypes.Block{ BaseFeePerGas: assets.NewWeiI(1), - Number: 1, + Number: 0, Hash: utils.NewHash(), Transactions: dynamicFeeTransactionsFromTipCaps(1), } - gas.SetRollingBlockHistory(bhe, []evmtypes.Block{b1}) - head := testutils.Head(1) - bhe.OnNewLongestChain(tests.Context(t), head) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(testutils.Head(0), nil).Once() + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &b0 + }).Once() + err := bhe.Start(ctx) + require.NoError(t, err) originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} attempts := []gas.EvmPriorAttempt{ {TxType: 0x2, TxHash: NewEvmHash(), DynamicFee: gas.DynamicFee{TipCap: originalFee.TipCap, FeeCap: originalFee.FeeCap}, BroadcastBeforeBlockNum: ptr(int64(0))}} - _, err := bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, attempts) + _, err = bhe.BumpDynamicFee(tests.Context(t), originalFee, maxGasPrice, attempts) require.Error(t, err) assert.True(t, pkgerrors.Is(err, commonfee.ErrConnectivity)) - assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 25 wei, which is above percentile=10%% (percentile tip cap: 1 wei) for blocks 1 thru 1 (checking 1 blocks)", attempts[0].TxHash)) + assert.Contains(t, err.Error(), fmt.Sprintf("transaction %s has tip cap of 25 wei, which is above percentile=10%% (percentile tip cap: 1 wei)", attempts[0].TxHash)) }) t.Run("BumpDynamicFee bumps the fee", func(t *testing.T) { @@ -2586,8 +2684,13 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.TipCapDefaultF = assets.NewWeiI(52) l1Oracle := rollupMocks.NewL1Oracle(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, nil).Once() + err := bhe.Start(ctx) + require.NoError(t, err) t.Run("when current tip cap is nil", func(t *testing.T) { originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} @@ -2648,6 +2751,130 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { }) } +func TestBlockHistoryEstimator_CheckInclusionPercentile_Calculation(t *testing.T) { + t.Parallel() + + t.Run("sets CheckInclusionPercentile price using the latest blocks, eip-1559 disabled", func(t *testing.T) { + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + cfg := gas.NewMockConfig() + bhCfg := newBlockHistoryConfig() + bhCfg.BlockDelayF = 0 + bhCfg.TransactionPercentileF = 35 + // Set BlockHistorySize larger than CheckInclusionBlocks to cache more blocks than needed for calculation + // Helps test whether the latest block is being used or not + bhCfg.BlockHistorySizeF = 3 + bhCfg.BatchSizeF = 0 + bhCfg.CheckInclusionBlocksF = 1 + bhCfg.CheckInclusionPercentileF = 100 + + geCfg := &gas.MockGasEstimatorConfig{} + geCfg.EIP1559DynamicFeesF = false + geCfg.PriceMaxF = assets.NewWeiI(1000) + geCfg.PriceMinF = assets.NewWeiI(0) + + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + + b0 := evmtypes.Block{ + Number: 0, + Hash: utils.NewHash(), + Transactions: legacyTransactionsFromGasPrices(1, 2, 3), + } + b1 := evmtypes.Block{ + Number: 1, + Hash: utils.NewHash(), + Transactions: legacyTransactionsFromGasPrices(4, 5, 6), + } + b2 := evmtypes.Block{ + Number: 2, + Hash: utils.NewHash(), + Transactions: legacyTransactionsFromGasPrices(7, 8, 9), + } + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 3 && + b[0].Args[0] == "0x2" && + b[1].Args[0] == "0x1" && + b[2].Args[0] == "0x0" + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &b2 + elems[1].Result = &b1 + elems[2].Result = &b0 + }) + + bhe.FetchBlocksAndRecalculate(tests.Context(t), testutils.Head(2)) + + price := gas.GetMaxPercentileGasPrice(bhe) + require.Equal(t, assets.NewWeiI(9), price) + + assert.Len(t, gas.GetRollingBlockHistory(bhe), 3) + }) + + t.Run("sets CheckInclusionPercentile price using the latest blocks, eip-1559 enabled", func(t *testing.T) { + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + cfg := gas.NewMockConfig() + bhCfg := newBlockHistoryConfig() + bhCfg.BlockDelayF = 0 + bhCfg.TransactionPercentileF = 35 + // Set BlockHistorySize larger than CheckInclusionBlocks to cache more blocks than needed for calculation + // Helps test whether the latest block is being used or not + bhCfg.BlockHistorySizeF = 3 + bhCfg.BatchSizeF = 0 + bhCfg.CheckInclusionBlocksF = 1 + bhCfg.CheckInclusionPercentileF = 100 + + geCfg := &gas.MockGasEstimatorConfig{} + geCfg.EIP1559DynamicFeesF = true + geCfg.PriceMaxF = assets.NewWeiI(1000) + geCfg.PriceMinF = assets.NewWeiI(0) + geCfg.TipCapMinF = assets.NewWeiI(0) + + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) + + b0 := evmtypes.Block{ + BaseFeePerGas: assets.NewWeiI(1), + Number: 0, + Hash: utils.NewHash(), + Transactions: dynamicFeeTransactionsFromTipCaps(1, 2, 3), + } + b1 := evmtypes.Block{ + BaseFeePerGas: assets.NewWeiI(2), + Number: 1, + Hash: utils.NewHash(), + Transactions: dynamicFeeTransactionsFromTipCaps(4, 5, 6), + } + b2 := evmtypes.Block{ + BaseFeePerGas: assets.NewWeiI(3), + Number: 2, + Hash: utils.NewHash(), + Transactions: dynamicFeeTransactionsFromTipCaps(7, 8, 9), + } + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 3 && + b[0].Args[0] == "0x2" && + b[1].Args[0] == "0x1" && + b[2].Args[0] == "0x0" + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &b2 + elems[1].Result = &b1 + elems[2].Result = &b0 + }) + + bhe.FetchBlocksAndRecalculate(tests.Context(t), testutils.Head(2)) + + price := gas.GetMaxPercentileTipCap(bhe) + require.Equal(t, assets.NewWeiI(9), price) + + assert.Len(t, gas.GetRollingBlockHistory(bhe), 3) + }) +} + // ptr takes pointer of anything func ptr[T any](v T) *T { return &v diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go index e64b6ad477..2c12ed426a 100644 --- a/core/chains/evm/gas/helpers_test.go +++ b/core/chains/evm/gas/helpers_test.go @@ -16,8 +16,8 @@ func init() { MaxStartTime = 1 * time.Second } -func (b *BlockHistoryEstimator) CheckConnectivity(attempts []EvmPriorAttempt) error { - return b.checkConnectivity(attempts) +func (b *BlockHistoryEstimator) HaltBumping(attempts []EvmPriorAttempt) error { + return b.haltBumping(attempts) } func BlockHistoryEstimatorFromInterface(bhe EvmEstimator) *BlockHistoryEstimator { @@ -52,12 +52,24 @@ func GetGasPrice(b *BlockHistoryEstimator) *assets.Wei { return b.gasPrice } +func GetMaxPercentileGasPrice(b *BlockHistoryEstimator) *assets.Wei { + b.maxPriceMu.RLock() + defer b.maxPriceMu.RUnlock() + return b.maxPercentileGasPrice +} + func GetTipCap(b *BlockHistoryEstimator) *assets.Wei { b.priceMu.RLock() defer b.priceMu.RUnlock() return b.tipCap } +func GetMaxPercentileTipCap(b *BlockHistoryEstimator) *assets.Wei { + b.maxPriceMu.RLock() + defer b.maxPriceMu.RUnlock() + return b.maxPercentileTipCap +} + func GetLatestBaseFee(b *BlockHistoryEstimator) *assets.Wei { b.latestMu.RLock() defer b.latestMu.RUnlock() diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 1c4db432ce..1977d139f9 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -343,7 +343,7 @@ func (o *OptimismL1Oracle) checkIsEcotone(ctx context.Context) (bool, error) { // if the chain has not upgraded to Ecotone, the isEcotone call will revert, this would be expected if err != nil { - o.logger.Infof("isEcotone() call failed, this can happen if chain has not upgraded: %w", err) + o.logger.Infof("isEcotone() call failed, this can happen if chain has not upgraded: %v", err) return false, nil } diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go index e947e9109d..2c8798d632 100644 --- a/core/chains/evm/gas/suggested_price_estimator.go +++ b/core/chains/evm/gas/suggested_price_estimator.go @@ -213,7 +213,7 @@ func (o *SuggestedPriceEstimator) BumpLegacyGas(ctx context.Context, originalFee err = pkgerrors.New("failed to refresh and return gas; gas price not set") return } - o.logger.Debugw("GasPrice", newGasPrice, "GasLimit", feeLimit) + o.logger.Debugw("BumpLegacyGas", "GasPrice", newGasPrice, "GasLimit", feeLimit) }) if !ok { return nil, 0, pkgerrors.New("estimator is not started") diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 26978b18d4..1c8996a46e 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -863,7 +863,7 @@ func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, curren } // Additional sanity checks, don't necessarily trust the RPC. if currentBlock == nil { - lp.lggr.Errorf("Unexpected nil block from RPC", "currentBlockNumber", currentBlockNumber) + lp.lggr.Errorw("Unexpected nil block from RPC", "currentBlockNumber", currentBlockNumber) return nil, pkgerrors.Errorf("Got nil block for %d", currentBlockNumber) } if currentBlock.Number != currentBlockNumber { diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index 8a4c46bd7a..1d24976073 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -394,9 +394,6 @@ func (o *DSORM) insertLogsWithinTx(ctx context.Context, logs []Log, tx sqlutil.D ON CONFLICT DO NOTHING` _, err := o.ds.NamedExecContext(ctx, query, logs[start:end]) - if err != nil { - return err - } if err != nil { if pkgerrors.Is(err, context.DeadlineExceeded) && batchInsertSize > 500 { // In case of DB timeouts, try to insert again with a smaller batch upto a limit @@ -971,6 +968,7 @@ func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si return logs, nil } +// TODO flaky BCF-3258 func (o *DSORM) FilteredLogs(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, _ string) ([]Log, error) { qs, args, err := (&pgDSLParser{}).buildQuery(o.chainID, filter.Expressions, limitAndSort) if err != nil { diff --git a/core/chains/evm/logpoller/parser.go b/core/chains/evm/logpoller/parser.go index 2e17c92ed6..e08ea93da7 100644 --- a/core/chains/evm/logpoller/parser.go +++ b/core/chains/evm/logpoller/parser.go @@ -21,6 +21,7 @@ const ( timestampFieldName = "block_timestamp" txHashFieldName = "tx_hash" eventSigFieldName = "event_sig" + defaultSort = "block_number DESC, log_index DESC" ) var ( @@ -249,11 +250,15 @@ func (v *pgDSLParser) whereClause(expressions []query.Expression, limiter query. segment := "WHERE evm_chain_id = :evm_chain_id" if len(expressions) > 0 { - exp, err := v.combineExpressions(expressions, query.AND) + exp, hasFinalized, err := v.combineExpressions(expressions, query.AND) if err != nil { return "", err } + if limiter.HasCursorLimit() && !hasFinalized { + return "", errors.New("cursor-base queries limited to only finalized blocks") + } + segment = fmt.Sprintf("%s AND %s", segment, exp) } @@ -268,15 +273,14 @@ func (v *pgDSLParser) whereClause(expressions []query.Expression, limiter query. return "", errors.New("invalid cursor direction") } - block, txHash, logIdx, err := valuesFromCursor(limiter.Limit.Cursor) + block, logIdx, _, err := valuesFromCursor(limiter.Limit.Cursor) if err != nil { return "", err } - segment = fmt.Sprintf("%s AND block_number %s= :cursor_block AND tx_hash %s= :cursor_txhash AND log_index %s :cursor_log_index", segment, op, op, op) + segment = fmt.Sprintf("%s AND (block_number %s :cursor_block_number OR (block_number = :cursor_block_number AND log_index %s :cursor_log_index))", segment, op, op) v.args.withField("cursor_block_number", block). - withField("cursor_txhash", common.HexToHash(txHash)). withField("cursor_log_index", logIdx) } @@ -302,7 +306,7 @@ func (v *pgDSLParser) orderClause(limiter query.LimitAndSort) (string, error) { } if len(sorting) == 0 { - return "", nil + return fmt.Sprintf("ORDER BY %s", defaultSort), nil } sort := make([]string, len(sorting)) @@ -319,7 +323,7 @@ func (v *pgDSLParser) orderClause(limiter query.LimitAndSort) (string, error) { case query.SortByBlock: name = blockFieldName case query.SortBySequence: - sort[idx] = fmt.Sprintf("block_number %s, tx_hash %s, log_index %s", order, order, order) + sort[idx] = fmt.Sprintf("block_number %s, log_index %s, tx_hash %s", order, order, order) continue case query.SortByTimestamp: @@ -352,24 +356,37 @@ func (v *pgDSLParser) getLastExpression() (string, error) { return exp, err } -func (v *pgDSLParser) combineExpressions(expressions []query.Expression, op query.BoolOperator) (string, error) { +func (v *pgDSLParser) combineExpressions(expressions []query.Expression, op query.BoolOperator) (string, bool, error) { grouped := len(expressions) > 1 clauses := make([]string, len(expressions)) + var isFinalized bool + for idx, exp := range expressions { if exp.IsPrimitive() { exp.Primitive.Accept(v) + switch prim := exp.Primitive.(type) { + case *primitives.Confidence: + isFinalized = prim.ConfidenceLevel == primitives.Finalized + case *confirmationsFilter: + isFinalized = prim.Confirmations == evmtypes.Finalized + } + clause, err := v.getLastExpression() if err != nil { - return "", err + return "", isFinalized, err } clauses[idx] = clause } else { - clause, err := v.combineExpressions(exp.BoolExpression.Expressions, exp.BoolExpression.BoolOperator) + clause, fin, err := v.combineExpressions(exp.BoolExpression.Expressions, exp.BoolExpression.BoolOperator) if err != nil { - return "", err + return "", isFinalized, err + } + + if fin { + isFinalized = fin } clauses[idx] = clause @@ -382,7 +399,7 @@ func (v *pgDSLParser) combineExpressions(expressions []query.Expression, op quer output = fmt.Sprintf("(%s)", output) } - return output, nil + return output, isFinalized, nil } func cmpOpToString(op primitives.ComparisonOperator) (string, error) { @@ -415,23 +432,30 @@ func orderToString(dir query.SortDirection) (string, error) { } } -func valuesFromCursor(cursor string) (int64, string, int, error) { +func valuesFromCursor(cursor string) (int64, int, []byte, error) { + partCount := 3 + parts := strings.Split(cursor, "-") - if len(parts) != 3 { - return 0, "", 0, fmt.Errorf("%w: must be composed as block-txhash-logindex", ErrUnexpectedCursorFormat) + if len(parts) != partCount { + return 0, 0, nil, fmt.Errorf("%w: must be composed as block-logindex-txHash", ErrUnexpectedCursorFormat) } block, err := strconv.ParseInt(parts[0], 10, 64) if err != nil { - return 0, "", 0, fmt.Errorf("%w: block number not parsable as int64", ErrUnexpectedCursorFormat) + return 0, 0, nil, fmt.Errorf("%w: block number not parsable as int64", ErrUnexpectedCursorFormat) + } + + logIdx, err := strconv.ParseInt(parts[1], 10, 32) + if err != nil { + return 0, 0, nil, fmt.Errorf("%w: log index not parsable as int", ErrUnexpectedCursorFormat) } - logIdx, err := strconv.ParseInt(parts[2], 10, 32) + txHash, err := hexutil.Decode(parts[2]) if err != nil { - return 0, "", 0, fmt.Errorf("%w: log index not parsable as int", ErrUnexpectedCursorFormat) + return 0, 0, nil, fmt.Errorf("%w: invalid transaction hash: %s", ErrUnexpectedCursorFormat, err.Error()) } - return block, parts[1], int(logIdx), nil + return block, int(logIdx), txHash, nil } type addressFilter struct { diff --git a/core/chains/evm/logpoller/parser_test.go b/core/chains/evm/logpoller/parser_test.go index 521aec14d8..5e99ec7ba8 100644 --- a/core/chains/evm/logpoller/parser_test.go +++ b/core/chains/evm/logpoller/parser_test.go @@ -10,6 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) func assertArgs(t *testing.T, args *queryArgs, numVals int) { @@ -33,7 +34,7 @@ func TestDSLParser(t *testing.T) { result, args, err := parser.buildQuery(chainID, expressions, limiter) require.NoError(t, err) - assert.Equal(t, "SELECT evm.logs.* FROM evm.logs WHERE evm_chain_id = :evm_chain_id", result) + assert.Equal(t, "SELECT evm.logs.* FROM evm.logs WHERE evm_chain_id = :evm_chain_id ORDER BY "+defaultSort, result) assertArgs(t, args, 1) }) @@ -46,22 +47,25 @@ func TestDSLParser(t *testing.T) { expressions := []query.Expression{ NewAddressFilter(common.HexToAddress("0x42")), NewEventSigFilter(common.HexToHash("0x21")), + NewConfirmationsFilter(types.Finalized), } - limiter := query.NewLimitAndSort(query.CursorLimit("10-0x42-5", query.CursorFollowing, 20)) + limiter := query.NewLimitAndSort(query.CursorLimit("10-5-0x42", query.CursorFollowing, 20)) result, args, err := parser.buildQuery(chainID, expressions, limiter) expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "AND (address = :address_0 AND event_sig = :event_sig_0) " + - "AND block_number >= :cursor_block AND tx_hash >= :cursor_txhash AND log_index > :cursor_log_index " + - "ORDER BY block_number ASC, tx_hash ASC, log_index ASC " + + "AND (address = :address_0 AND event_sig = :event_sig_0 " + + "AND block_number <= " + + "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + + "AND (block_number > :cursor_block_number OR (block_number = :cursor_block_number AND log_index > :cursor_log_index)) " + + "ORDER BY block_number ASC, log_index ASC, tx_hash ASC " + "LIMIT 20" require.NoError(t, err) assert.Equal(t, expected, result) - assertArgs(t, args, 6) + assertArgs(t, args, 5) }) t.Run("query with limit and no order by", func(t *testing.T) { @@ -80,6 +84,7 @@ func TestDSLParser(t *testing.T) { "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + "AND (address = :address_0 AND event_sig = :event_sig_0) " + + "ORDER BY " + defaultSort + " " + "LIMIT 20" require.NoError(t, err) @@ -100,7 +105,7 @@ func TestDSLParser(t *testing.T) { expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "ORDER BY block_number DESC, tx_hash DESC, log_index DESC" + "ORDER BY block_number DESC, log_index DESC, tx_hash DESC" require.NoError(t, err) assert.Equal(t, expected, result) @@ -138,9 +143,8 @@ func TestDSLParser(t *testing.T) { query.TxHash(common.HexToHash("0x84").String()), query.Block(99, primitives.Neq), query.Confidence(primitives.Finalized), - query.Confidence(primitives.Unconfirmed), } - limiter := query.NewLimitAndSort(query.CursorLimit("10-0x42-20", query.CursorPrevious, 20)) + limiter := query.NewLimitAndSort(query.CursorLimit("10-20-0x42", query.CursorPrevious, 20)) result, args, err := parser.buildQuery(chainID, expressions, limiter) expected := "SELECT evm.logs.* " + @@ -150,15 +154,14 @@ func TestDSLParser(t *testing.T) { "AND tx_hash = :tx_hash_0 " + "AND block_number != :block_number_0 " + "AND block_number <= " + - "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) " + - "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + - "AND block_number <= :cursor_block AND tx_hash <= :cursor_txhash AND log_index < :cursor_log_index " + - "ORDER BY block_number DESC, tx_hash DESC, log_index DESC LIMIT 20" + "(SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)) " + + "AND (block_number < :cursor_block_number OR (block_number = :cursor_block_number AND log_index < :cursor_log_index)) " + + "ORDER BY block_number DESC, log_index DESC, tx_hash DESC LIMIT 20" require.NoError(t, err) assert.Equal(t, expected, result) - assertArgs(t, args, 8) + assertArgs(t, args, 6) }) t.Run("query for finality", func(t *testing.T) { @@ -175,7 +178,7 @@ func TestDSLParser(t *testing.T) { expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "AND block_number <= (SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)" + "AND block_number <= (SELECT finalized_block_number FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) @@ -194,7 +197,7 @@ func TestDSLParser(t *testing.T) { expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)" + "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) @@ -213,7 +216,7 @@ func TestDSLParser(t *testing.T) { expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)" + "AND block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) @@ -243,7 +246,7 @@ func TestDSLParser(t *testing.T) { expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0" + "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0 ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) @@ -268,7 +271,7 @@ func TestDSLParser(t *testing.T) { expected := "SELECT evm.logs.* " + "FROM evm.logs " + "WHERE evm_chain_id = :evm_chain_id " + - "AND topics[:topic_index_0] > :topic_value_0 AND topics[:topic_index_0] < :topic_value_1" + "AND topics[:topic_index_0] > :topic_value_0 AND topics[:topic_index_0] < :topic_value_1 ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) @@ -306,7 +309,7 @@ func TestDSLParser(t *testing.T) { "WHERE evm_chain_id = :evm_chain_id " + "AND (block_timestamp >= :block_timestamp_0 " + "AND (tx_hash = :tx_hash_0 " + - "OR block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1)))" + "OR block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1))) ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) @@ -357,7 +360,7 @@ func TestDSLParser(t *testing.T) { "AND (tx_hash = :tx_hash_0 " + "OR (block_number <= (SELECT greatest(block_number - :confs_0, 0) FROM evm.log_poller_blocks WHERE evm_chain_id = :evm_chain_id ORDER BY block_number DESC LIMIT 1) " + "AND substring(data from 32*:word_index_0+1 for 32) > :word_value_0 " + - "AND substring(data from 32*:word_index_0+1 for 32) <= :word_value_1)))" + "AND substring(data from 32*:word_index_0+1 for 32) <= :word_value_1))) ORDER BY " + defaultSort require.NoError(t, err) assert.Equal(t, expected, result) diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go index caba4d3806..dcf15a4fa2 100644 --- a/core/chains/evm/txmgr/builder.go +++ b/core/chains/evm/txmgr/builder.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -26,7 +26,7 @@ func NewTxm( clientErrors config.ClientErrors, dbConfig DatabaseConfig, listenerConfig ListenerConfig, - client evmclient.Client, + client client.Client, lggr logger.Logger, logPoller logpoller.LogPoller, keyStore keystore.Eth, @@ -77,7 +77,7 @@ func NewEvmTxm( resender *Resender, tracker *Tracker, ) *Txm { - return txmgr.NewTxm(chainId, cfg, txCfg, keyStore, lggr, checkerFactory, fwdMgr, txAttemptBuilder, txStore, broadcaster, confirmer, resender, tracker) + return txmgr.NewTxm(chainId, cfg, txCfg, keyStore, lggr, checkerFactory, fwdMgr, txAttemptBuilder, txStore, broadcaster, confirmer, resender, tracker, client.NewTxError) } // NewEvmResender creates a new concrete EvmResender diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index a3ae0a0a5d..6b107b222a 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -3223,7 +3223,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { require.NoError(t, err) require.NotNil(t, dbTx) require.Equal(t, txmgrcommon.TxFatalError, dbTx.State) - require.Equal(t, "transaction terminally stuck", dbTx.Error.String) + require.Equal(t, client.TerminallyStuckMsg, dbTx.Error.String) }) } diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index ce64f816cd..fd38eb7a8c 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -1061,16 +1061,26 @@ func (o *evmTxStore) FindTxWithIdempotencyKey(ctx context.Context, idempotencyKe var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - var dbEtx DbEthTx - err = o.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE idempotency_key = $1 and evm_chain_id = $2`, idempotencyKey, chainID.String()) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, nil + err = o.Transact(ctx, true, func(orm *evmTxStore) error { + var dbEtx DbEthTx + err = o.q.GetContext(ctx, &dbEtx, `SELECT * FROM evm.txes WHERE idempotency_key = $1 and evm_chain_id = $2`, idempotencyKey, chainID.String()) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil + } + return pkgerrors.Wrap(err, "FindTxWithIdempotencyKey failed to load evm.txes") } - return nil, pkgerrors.Wrap(err, "FindTxWithIdempotencyKey failed to load evm.txes") - } - etx = new(Tx) - dbEtx.ToTx(etx) + etx = new(Tx) + dbEtx.ToTx(etx) + etxArr := []*Tx{etx} + if err = orm.LoadTxesAttempts(ctx, etxArr); err != nil { + return fmt.Errorf("FindTxWithIdempotencyKey failed to load evm.tx_attempts: %w", err) + } + if err = orm.loadEthTxesAttemptsReceipts(ctx, etxArr); err != nil { + return fmt.Errorf("FindTxWithIdempotencyKey failed to load evm.receipts: %w", err) + } + return nil + }) return } diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 71b1bd5285..afb8de4ca5 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -698,7 +698,7 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - t.Run("returns nil if no results", func(t *testing.T) { + t.Run("returns nil error if no results", func(t *testing.T) { idempotencyKey := "777" etx, err := txStore.FindTxWithIdempotencyKey(tests.Context(t), idempotencyKey, big.NewInt(0)) require.NoError(t, err) diff --git a/core/chains/evm/txmgr/stuck_tx_detector.go b/core/chains/evm/txmgr/stuck_tx_detector.go index 23cb9b2698..1beb857af8 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector.go +++ b/core/chains/evm/txmgr/stuck_tx_detector.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/common/txmgr" "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "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/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" ) @@ -343,7 +344,7 @@ func (d *stuckTxDetector) detectStuckTransactionsZkEVM(ctx context.Context, txs for i, req := range txReqs { txHash := req.Args[0].(common.Hash) if req.Error != nil { - d.lggr.Debugf("failed to get transaction by hash (%s): %w", txHash.String(), req.Error) + d.lggr.Debugf("failed to get transaction by hash (%s): %v", txHash.String(), req.Error) continue } result := *txRes[i] @@ -363,13 +364,6 @@ func (d *stuckTxDetector) SetPurgeBlockNum(fromAddress common.Address, blockNum } func (d *stuckTxDetector) StuckTxFatalError() *string { - var errorMsg string - switch d.chainType { - case chaintype.ChainScroll, chaintype.ChainZkEvm: - errorMsg = "transaction skipped by chain" - default: - errorMsg = "transaction terminally stuck" - } - + errorMsg := client.TerminallyStuckMsg return &errorMsg } diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index de5847dc71..dac0ef29cd 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -33,6 +34,7 @@ import ( evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" ksmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -586,6 +588,197 @@ func TestTxm_Reset(t *testing.T) { }) } +func TestTxm_GetTransactionStatus(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + feeLimit := uint64(10_000) + gcfg := configtest.NewTestGeneralConfig(t) + cfg := evmtest.NewChainScopedConfig(t, gcfg) + + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() + feeEstimator := gasmocks.NewEvmFeeEstimator(t) + feeEstimator.On("Start", mock.Anything).Return(nil).Once() + feeEstimator.On("OnNewLongestChain", mock.Anything, mock.Anything).Once() + txm, err := makeTestEvmTxm(t, db, ethClient, feeEstimator, cfg.EVM(), cfg.EVM().GasEstimator(), cfg.EVM().Transactions(), gcfg.Database(), gcfg.Database().Listener(), ethKeyStore) + require.NoError(t, err) + err = txm.Start(ctx) + require.NoError(t, err) + + head := &evmtypes.Head{ + Hash: utils.NewHash(), + Number: 100, + Parent: &evmtypes.Head{ + Hash: utils.NewHash(), + Number: 99, + IsFinalized: true, + }, + } + txm.OnNewLongestChain(ctx, head) + + t.Run("returns error if transaction not found", func(t *testing.T) { + idempotencyKey := uuid.New().String() + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.Error(t, err, fmt.Sprintf("failed to find transaction with IdempotencyKey: %s", idempotencyKey)) + require.Equal(t, commontypes.Unknown, state) + }) + + t.Run("returns unknown for unstarted state", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + tx := &txmgr.Tx{ + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxUnstarted, + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.NoError(t, err) + require.Equal(t, commontypes.Unknown, state) + }) + + t.Run("returns unknown for in-progress state", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + nonce := evmtypes.Nonce(0) + tx := &txmgr.Tx{ + Sequence: &nonce, + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxInProgress, + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.NoError(t, err) + require.Equal(t, commontypes.Unknown, state) + }) + + t.Run("returns unconfirmed for unconfirmed state", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + nonce := evmtypes.Nonce(0) + broadcast := time.Now() + tx := &txmgr.Tx{ + Sequence: &nonce, + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxUnconfirmed, + BroadcastAt: &broadcast, + InitialBroadcastAt: &broadcast, + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.NoError(t, err) + require.Equal(t, commontypes.Unconfirmed, state) + }) + + t.Run("returns unconfirmed for confirmed state", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + nonce := evmtypes.Nonce(0) + broadcast := time.Now() + tx := &txmgr.Tx{ + Sequence: &nonce, + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxConfirmed, + BroadcastAt: &broadcast, + InitialBroadcastAt: &broadcast, + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) + require.NoError(t, err) + attempt := cltest.NewLegacyEthTxAttempt(t, tx.ID) + err = txStore.InsertTxAttempt(ctx, &attempt) + require.NoError(t, err) + // Insert receipt for finalized block num + mustInsertEthReceipt(t, txStore, head.Parent.Number, head.ParentHash, attempt.Hash) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.NoError(t, err) + require.Equal(t, commontypes.Unconfirmed, state) + }) + + t.Run("returns unconfirmed for confirmed missing receipt state", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + nonce := evmtypes.Nonce(0) + broadcast := time.Now() + tx := &txmgr.Tx{ + Sequence: &nonce, + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxConfirmedMissingReceipt, + BroadcastAt: &broadcast, + InitialBroadcastAt: &broadcast, + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.NoError(t, err) + require.Equal(t, commontypes.Unconfirmed, state) + }) + + t.Run("returns fatal for fatal error state with terminally stuck error", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + nonce := evmtypes.Nonce(0) + broadcast := time.Now() + tx := &txmgr.Tx{ + Sequence: &nonce, + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxFatalError, + Error: null.NewString(evmclient.TerminallyStuckMsg, true), + BroadcastAt: &broadcast, + InitialBroadcastAt: &broadcast, + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.Equal(t, commontypes.Fatal, state) + require.Error(t, err, evmclient.TerminallyStuckMsg) + }) + + t.Run("returns failed for fatal error state with other error", func(t *testing.T) { + idempotencyKey := uuid.New().String() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + errorMsg := "something went wrong" + tx := &txmgr.Tx{ + IdempotencyKey: &idempotencyKey, + FromAddress: fromAddress, + EncodedPayload: []byte{1, 2, 3}, + FeeLimit: feeLimit, + State: txmgrcommon.TxFatalError, + Error: null.NewString(errorMsg, true), + } + err := txStore.InsertTx(ctx, tx) + require.NoError(t, err) + state, err := txm.GetTransactionStatus(ctx, idempotencyKey) + require.Equal(t, commontypes.Failed, state) + require.Error(t, err, errorMsg) + }) +} + func newTxStore(t *testing.T, db *sqlx.DB) txmgr.EvmTxStore { return txmgr.NewTxStore(db, logger.Test(t)) } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index d6f99955e1..e12b069277 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -263,9 +263,9 @@ func handleNodeVersioning(ctx context.Context, db *sqlx.DB, appLggr logger.Logge if backupCfg.Mode() != config.DatabaseBackupModeNone && backupCfg.OnVersionUpgrade() { if err = takeBackupIfVersionUpgrade(cfg.URL(), rootDir, cfg.Backup(), appLggr, appv, dbv, healthReportPort); err != nil { if errors.Is(err, sql.ErrNoRows) { - appLggr.Debugf("Failed to find any node version in the DB: %w", err) + appLggr.Debugf("Failed to find any node version in the DB: %v", err) } else if strings.Contains(err.Error(), "relation \"node_versions\" does not exist") { - appLggr.Debugf("Failed to find any node version in the DB, the node_versions table does not exist yet: %w", err) + appLggr.Debugf("Failed to find any node version in the DB, the node_versions table does not exist yet: %v", err) } else { return fmt.Errorf("initializeORM#FindLatestNodeVersion: %w", err) } @@ -830,7 +830,7 @@ func (t *promptingAPIInitializer) Initialize(ctx context.Context, orm sessions.B continue } if err = orm.CreateUser(ctx, &user); err != nil { - lggr.Errorf("Error creating API user: ", err, "err") + lggr.Errorw("Error creating API user", "err", err) } return user, err } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 780105d986..3ecd3eed40 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -173,6 +173,10 @@ func initLocalSubCmds(s *Shell, safe bool) []cli.Command { Name: "dangerWillRobinson", Usage: "set to true to enable dropping non-test databases", }, + cli.BoolFlag{ + Name: "force", + Usage: "set to true to force the reset by dropping any existing connections to the database", + }, }, }, { @@ -186,6 +190,10 @@ func initLocalSubCmds(s *Shell, safe bool) []cli.Command { Name: "user-only", Usage: "only include test user fixture", }, + cli.BoolFlag{ + Name: "force", + Usage: "set to true to force the reset by dropping any existing connections to the database", + }, }, }, { @@ -748,7 +756,7 @@ func (s *Shell) ResetDatabase(c *cli.Context) error { } dangerMode := c.Bool("dangerWillRobinson") - + force := c.Bool("force") dbname := parsed.Path[1:] if !dangerMode && !strings.HasSuffix(dbname, "_test") { return s.errorOut(fmt.Errorf("cannot reset database named `%s`. This command can only be run against databases with a name that ends in `_test`, to prevent accidental data loss. If you REALLY want to reset this database, pass in the -dangerWillRobinson option", dbname)) @@ -756,7 +764,7 @@ func (s *Shell) ResetDatabase(c *cli.Context) error { lggr := s.Logger lggr.Infof("Resetting database: %#v", parsed.String()) lggr.Debugf("Dropping and recreating database: %#v", parsed.String()) - if err := dropAndCreateDB(parsed); err != nil { + if err := dropAndCreateDB(parsed, force); err != nil { return s.errorOut(err) } lggr.Debugf("Migrating database: %#v", parsed.String()) @@ -1079,7 +1087,7 @@ func newConnection(cfg dbConfig) (*sqlx.DB, error) { return pg.NewConnection(parsed.String(), cfg.Dialect(), cfg) } -func dropAndCreateDB(parsed url.URL) (err error) { +func dropAndCreateDB(parsed url.URL, force bool) (err error) { // Cannot drop the database if we are connected to it, so we must connect // to a different one. template1 should be present on all postgres installations dbname := parsed.Path[1:] @@ -1093,7 +1101,13 @@ func dropAndCreateDB(parsed url.URL) (err error) { err = multierr.Append(err, cerr) } }() - + if force { + // supports pg < 13. https://stackoverflow.com/questions/17449420/postgresql-unable-to-drop-database-because-of-some-auto-connections-to-db + _, err = db.Exec(fmt.Sprintf("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '%s';", dbname)) + if err != nil { + return fmt.Errorf("unable to terminate connections to postgres database: %v", err) + } + } _, err = db.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, dbname)) if err != nil { return fmt.Errorf("unable to drop postgres database: %v", err) diff --git a/core/config/capabilities_config.go b/core/config/capabilities_config.go index 8cde986ccb..ae542c062c 100644 --- a/core/config/capabilities_config.go +++ b/core/config/capabilities_config.go @@ -1,6 +1,17 @@ package config +import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +type CapabilitiesExternalRegistry interface { + Address() string + NetworkID() string + ChainID() string + RelayID() types.RelayID +} + type Capabilities interface { Peering() P2P - // NOTE: RegistrySyncer will need config with relay ID, chain ID and contract address when implemented + ExternalRegistry() CapabilitiesExternalRegistry } diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index cb097b988c..3d2575aaca 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -442,6 +442,14 @@ DeltaReconcile = '1m' # Default # but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example +[Capabilities.ExternalRegistry] +# Address is the address for the capabilities registry contract. +Address = '0x0' # Example +# NetworkID identifies the target network where the remote registry is located. +NetworkID = 'evm' # Default +# ChainID identifies the target chain id where the remote registry is located. +ChainID = '1' # Default + [Capabilities.Peering] # IncomingMessageBufferSize is the per-remote number of incoming # messages to buffer. Any additional messages received on top of those diff --git a/core/config/toml/types.go b/core/config/toml/types.go index 5c41f60fc3..9f2b7d0547 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -1410,12 +1410,34 @@ func (m *MercurySecrets) ValidateConfig() (err error) { return err } +type ExternalRegistry struct { + Address *string + NetworkID *string + ChainID *string +} + +func (r *ExternalRegistry) setFrom(f *ExternalRegistry) { + if f.Address != nil { + r.Address = f.Address + } + + if f.NetworkID != nil { + r.NetworkID = f.NetworkID + } + + if f.ChainID != nil { + r.ChainID = f.ChainID + } +} + type Capabilities struct { - Peering P2P `toml:",omitempty"` + Peering P2P `toml:",omitempty"` + ExternalRegistry ExternalRegistry `toml:",omitempty"` } func (c *Capabilities) setFrom(f *Capabilities) { c.Peering.setFrom(&f.Peering) + c.ExternalRegistry.setFrom(&f.ExternalRegistry) } type ThresholdKeyShareSecrets struct { diff --git a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go index 6cb4ee30be..4b392cac40 100644 --- a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go +++ b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go @@ -57,8 +57,8 @@ type AutomationRegistrar23TriggerRegistrationStorage struct { } var AutomationRegistrarMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b5060405162003556380380620035568339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612d02620008546000396000818161029b015281816105a601526106390152600081816104b301528181610b4c01528181610bb50152818161165b01526116b40152612d026000f3fe6080604052600436106101295760003560e01c80637e776f7f116100a5578063a4c0ed3611610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063a4c0ed3614610461578063b5ff5b411461048157600080fd5b80637e776f7f146102d257806388b12d55146103285780638da5cb5b146103f3578063a2b1ff941461041e57600080fd5b8063367b9b4f116100fc57806366ab87f9116100e157806366ab87f9146102695780636bf7d75f1461028957806379ba5097146102bd57600080fd5b8063367b9b4f146101fd5780635ab1bd531461021d57600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba5780633188a2ce146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611f51565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611f81565b610515565b6040516101849190612006565b6101cd6101c836600461231d565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f6366004612352565b610710565b005b34801561020957600080fd5b506101fb61021836600461239c565b610859565b34801561022957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561027557600080fd5b506101fb610284366004612464565b6108eb565b34801561029557600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c957600080fd5b506101fb610a32565b3480156102de57600080fd5b506103186102ed36600461253a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561033457600080fd5b506103ba610343366004612557565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103ff57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610244565b34801561042a57600080fd5b506101cd61043936600461253a565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561046d57600080fd5b506101fb61047c366004612570565b610b34565b34801561048d57600080fd5b506101fb61049c3660046125f9565b610c62565b3480156104ad57600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612557565b610d41565b34801561050157600080fd5b506101fb61051036600461253a565b610f08565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611f9c565b600281111561057657610576611f9c565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f1c565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fbe909392919063ffffffff16565b61070a823361109a565b92915050565b610718611501565b60008160405160200161072b91906126f6565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181528282528051602091820120600081815260058352839020606085018452805473ffffffffffffffffffffffffffffffffffffffff808216808852740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169487019490945260019091015490921692840192909252909250610807576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040812090815560010180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561085361084d846128b2565b83611584565b50505050565b610861611501565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6108f3611501565b805182511461092e576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b8251811015610a035781818151811061098c5761098c6128be565b6020026020010151600460008584815181106109aa576109aa6128be565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806109fb9061291c565b915050610971565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ab8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610ba3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610bb18284018461231d565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610c3c576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610c5a818661109a565b505050505050565b610c6a611501565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cb757610cb7611f9c565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d3490859085908590612954565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610ddb575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e11576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e5f576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610ed99273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff166118ef565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f10611501565b610f198161194a565b50565b60006bffffffffffffffffffffffff821115610fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610aaf565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526108539085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a3f565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611110576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611161576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f9919061297f565b61122f576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001611242919061299c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112d5576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161135799989796959493929190612b08565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936113da93839116600281111561139d5761139d611f9c565b60028111156113ae576113ae611f9c565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611b4b565b1561144257608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561141283612bc3565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061143b8583611584565b90506114f9565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610aaf565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861161498939792969095939492939092909190600401612be6565b6020604051808303816000875af1158015611633573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116579190612c74565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16036117ce5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161170791815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161173493929190612c8d565b6020604051808303816000875af1158015611753573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611777919061297f565b9050806117c8576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610aaf565b506118aa565b61180f8286602001516bffffffffffffffffffffffff168760a0015173ffffffffffffffffffffffffffffffffffffffff16611bf09092919063ffffffff16565b60208501516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff83169063948108f790604401600060405180830381600087803b15801561189157600080fd5b505af11580156118a5573d6000803e3d6000fd5b505050505b80847fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8760c001516040516118df9190611f51565b60405180910390a3949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119459084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611018565b505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036119c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610aaf565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611aa1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d729092919063ffffffff16565b8051909150156119455780806020019051810190611abf919061297f565b611945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aaf565b60008083516002811115611b6157611b61611f9c565b03611b6e5750600061070a565b600183516002811115611b8357611b83611f9c565b148015611bb6575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611bc35750600061070a565b826020015163ffffffff16836040015163ffffffff161015611be75750600161070a565b50600092915050565b801580611c9057506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8e9190612c74565b155b611d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610aaf565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119459084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611018565b60606114f98484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611da69190612cd9565b60006040518083038185875af1925050503d8060008114611de3576040519150601f19603f3d011682016040523d82523d6000602084013e611de8565b606091505b5091509150611df987838387611e04565b979650505050505050565b60608315611e9a578251600003611e935773ffffffffffffffffffffffffffffffffffffffff85163b611e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aaf565b50816114f9565b6114f98383815115611eaf5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aaf9190611f51565b60005b83811015611efe578181015183820152602001611ee6565b50506000910152565b60008151808452611f1f816020860160208601611ee3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f646020830184611f07565b9392505050565b803560ff81168114611f7c57600080fd5b919050565b600060208284031215611f9357600080fd5b611f6482611f6b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110612002577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050612019828451611fcb565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff811182821017156120925761209261203f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156120df576120df61203f565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1957600080fd5b8035611f7c816120e7565b80356bffffffffffffffffffffffff81168114611f7c57600080fd5b803563ffffffff81168114611f7c57600080fd5b600082601f83011261215557600080fd5b813567ffffffffffffffff81111561216f5761216f61203f565b6121a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612098565b8181528460208386010111156121b557600080fd5b816020850160208301376000918101602001919091529392505050565b600061016082840312156121e557600080fd5b6121ed61206e565b90506121f882612109565b815261220660208301612114565b602082015261221760408301612109565b604082015261222860608301612130565b606082015261223960808301611f6b565b608082015261224a60a08301612109565b60a082015260c082013567ffffffffffffffff8082111561226a57600080fd5b61227685838601612144565b60c084015260e084013591508082111561228f57600080fd5b61229b85838601612144565b60e0840152610100915081840135818111156122b657600080fd5b6122c286828701612144565b8385015250610120915081840135818111156122dd57600080fd5b6122e986828701612144565b83850152506101409150818401358181111561230457600080fd5b61231086828701612144565b8385015250505092915050565b60006020828403121561232f57600080fd5b813567ffffffffffffffff81111561234657600080fd5b6114f9848285016121d2565b60006020828403121561236457600080fd5b813567ffffffffffffffff81111561237b57600080fd5b82016101608185031215611f6457600080fd5b8015158114610f1957600080fd5b600080604083850312156123af57600080fd5b82356123ba816120e7565b915060208301356123ca8161238e565b809150509250929050565b600067ffffffffffffffff8211156123ef576123ef61203f565b5060051b60200190565b600082601f83011261240a57600080fd5b8135602061241f61241a836123d5565b612098565b82815260059290921b8401810191818101908684111561243e57600080fd5b8286015b848110156124595780358352918301918301612442565b509695505050505050565b60008060006060848603121561247957600080fd5b8335612484816120e7565b925060208481013567ffffffffffffffff808211156124a257600080fd5b818701915087601f8301126124b657600080fd5b81356124c461241a826123d5565b81815260059190911b8301840190848101908a8311156124e357600080fd5b938501935b8285101561250a5784356124fb816120e7565b825293850193908501906124e8565b96505050604087013592508083111561252257600080fd5b5050612530868287016123f9565b9150509250925092565b60006020828403121561254c57600080fd5b8135611f64816120e7565b60006020828403121561256957600080fd5b5035919050565b6000806000806060858703121561258657600080fd5b8435612591816120e7565b935060208501359250604085013567ffffffffffffffff808211156125b557600080fd5b818701915087601f8301126125c957600080fd5b8135818111156125d857600080fd5b8860208285010111156125ea57600080fd5b95989497505060200194505050565b60008060006060848603121561260e57600080fd5b61261784611f6b565b925060208401356003811061262b57600080fd5b915061263960408501612130565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261267757600080fd5b830160208101925035905067ffffffffffffffff81111561269757600080fd5b8036038213156126a657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526127246020820161270a84612109565b73ffffffffffffffffffffffffffffffffffffffff169052565b600061273260208401612114565b6bffffffffffffffffffffffff811660408401525061275360408401612109565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061277c60608401612130565b63ffffffff811660808401525061279560808401611f6b565b60ff811660a0840152506127ab60a08401612109565b73ffffffffffffffffffffffffffffffffffffffff811660c0840152506127d560c0840184612642565b6101608060e08601526127ed610180860183856126ad565b92506127fc60e0870187612642565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008188870301818901526128368686856126ad565b9550612844818a018a612642565b95509250506101208188870301818901526128608686856126ad565b955061286e818a018a612642565b955092505061014081888703018189015261288a8686856126ad565b9550612898818a018a612642565b955092505080878603018388015250611df98484836126ad565b600061070a36836121d2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361294d5761294d6128ed565b5060010190565b60ff841681526060810161296b6020830185611fcb565b63ffffffff83166040830152949350505050565b60006020828403121561299157600080fd5b8151611f648161238e565b602081526129c360208201835173ffffffffffffffffffffffffffffffffffffffff169052565b600060208301516129e460408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612a66610180850183611f07565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152612aa48584611f07565b945080880151925050610120818786030181880152612ac38584611f07565b945080880151925050610140818786030181880152612ae28584611f07565b908801518782039092018488015293509050612afe8382611f07565b9695505050505050565b6000610120808352612b1c8184018d611f07565b90508281036020840152612b30818c611f07565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612b758188611f07565b905082810360c0840152612b898187611f07565b905082810360e0840152612b9d8186611f07565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612bdc57612bdc6128ed565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612c3d81840187611f07565b905082810360c0840152612c518186611f07565b905082810360e0840152612c658185611f07565b9b9a5050505050505050505050565b600060208284031215612c8657600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612cd06060830184611f07565b95945050505050565b60008251612ceb818460208701611ee3565b919091019291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60c06040523480156200001157600080fd5b5060405162003571380380620035718339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612d1d620008546000396000818161029b015281816105a601526106390152600081816104b301528181610b4c01528181610bb50152818161166101526116ba0152612d1d6000f3fe6080604052600436106101295760003560e01c80637e776f7f116100a5578063a4c0ed3611610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063a4c0ed3614610461578063b5ff5b411461048157600080fd5b80637e776f7f146102d257806388b12d55146103285780638da5cb5b146103f3578063a2b1ff941461041e57600080fd5b8063367b9b4f116100fc57806366ab87f9116100e157806366ab87f9146102695780636bf7d75f1461028957806379ba5097146102bd57600080fd5b8063367b9b4f146101fd5780635ab1bd531461021d57600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba5780633188a2ce146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611f57565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611f87565b610515565b604051610184919061200c565b6101cd6101c8366004612323565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f6366004612358565b610710565b005b34801561020957600080fd5b506101fb6102183660046123a2565b610859565b34801561022957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561027557600080fd5b506101fb61028436600461246a565b6108eb565b34801561029557600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156102c957600080fd5b506101fb610a32565b3480156102de57600080fd5b506103186102ed366004612540565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561033457600080fd5b506103ba61034336600461255d565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103ff57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610244565b34801561042a57600080fd5b506101cd610439366004612540565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561046d57600080fd5b506101fb61047c366004612576565b610b34565b34801561048d57600080fd5b506101fb61049c3660046125ff565b610c62565b3480156104ad57600080fd5b506102447f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f036600461255d565b610d41565b34801561050157600080fd5b506101fb610510366004612540565b610f08565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611fa2565b600281111561057657610576611fa2565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f1c565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fbe909392919063ffffffff16565b61070a823361109a565b92915050565b610718611507565b60008160405160200161072b91906126fc565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181528282528051602091820120600081815260058352839020606085018452805473ffffffffffffffffffffffffffffffffffffffff808216808852740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169487019490945260019091015490921692840192909252909250610807576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260056020526040812090815560010180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561085361084d846128b8565b8361158a565b50505050565b610861611507565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6108f3611507565b805182511461092e576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b8251811015610a035781818151811061098c5761098c6128c4565b6020026020010151600460008584815181106109aa576109aa6128c4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806109fb90612922565b915050610971565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ab8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610ba3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610bb182840184612323565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610c3c576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610c5a818661109a565b505050505050565b610c6a611507565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cb757610cb7611fa2565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d349085908590859061295a565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610ddb575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e11576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e5f576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610ed99273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff166118f5565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f10611507565b610f1981611950565b50565b60006bffffffffffffffffffffffff821115610fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610aaf565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526108539085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a45565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611110576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611161576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f99190612985565b61122f576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360405160200161124291906129a2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112d5576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817fd178af9fe30387562e61bb997b245b7f49c26aad1e50c39d7b438ffa6c41b3068660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e602001518f60a0015160405161135d9a99989796959493929190612b0e565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936113e09383911660028111156113a3576113a3611fa2565b60028111156113b4576113b4611fa2565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611b51565b1561144857608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561141883612bed565b91906101000a81548163ffffffff021916908363ffffffff16021790555050611441858361158a565b90506114ff565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610aaf565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861161a98939792969095939492939092909190600401612c10565b6020604051808303816000875af1158015611639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061165d9190612c8f565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16036117d45760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161170d91815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161173a93929190612ca8565b6020604051808303816000875af1158015611759573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177d9190612985565b9050806117ce576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610aaf565b506118b0565b6118158286602001516bffffffffffffffffffffffff168760a0015173ffffffffffffffffffffffffffffffffffffffff16611bf69092919063ffffffff16565b60208501516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff83169063948108f790604401600060405180830381600087803b15801561189757600080fd5b505af11580156118ab573d6000803e3d6000fd5b505050505b80847fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8760c001516040516118e59190611f57565b60405180910390a3949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261194b9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611018565b505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036119cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610aaf565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611aa7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d789092919063ffffffff16565b80519091501561194b5780806020019051810190611ac59190612985565b61194b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aaf565b60008083516002811115611b6757611b67611fa2565b03611b745750600061070a565b600183516002811115611b8957611b89611fa2565b148015611bbc575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611bc95750600061070a565b826020015163ffffffff16836040015163ffffffff161015611bed5750600161070a565b50600092915050565b801580611c9657506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611c70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c949190612c8f565b155b611d22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610aaf565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261194b9084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611018565b60606114ff8484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611dac9190612cf4565b60006040518083038185875af1925050503d8060008114611de9576040519150601f19603f3d011682016040523d82523d6000602084013e611dee565b606091505b5091509150611dff87838387611e0a565b979650505050505050565b60608315611ea0578251600003611e995773ffffffffffffffffffffffffffffffffffffffff85163b611e99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aaf565b50816114ff565b6114ff8383815115611eb55781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aaf9190611f57565b60005b83811015611f04578181015183820152602001611eec565b50506000910152565b60008151808452611f25816020860160208601611ee9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6a6020830184611f0d565b9392505050565b803560ff81168114611f8257600080fd5b919050565b600060208284031215611f9957600080fd5b611f6a82611f71565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110612008577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600060608201905061201f828451611fd1565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff8111828210171561209857612098612045565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156120e5576120e5612045565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1957600080fd5b8035611f82816120ed565b80356bffffffffffffffffffffffff81168114611f8257600080fd5b803563ffffffff81168114611f8257600080fd5b600082601f83011261215b57600080fd5b813567ffffffffffffffff81111561217557612175612045565b6121a660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161209e565b8181528460208386010111156121bb57600080fd5b816020850160208301376000918101602001919091529392505050565b600061016082840312156121eb57600080fd5b6121f3612074565b90506121fe8261210f565b815261220c6020830161211a565b602082015261221d6040830161210f565b604082015261222e60608301612136565b606082015261223f60808301611f71565b608082015261225060a0830161210f565b60a082015260c082013567ffffffffffffffff8082111561227057600080fd5b61227c8583860161214a565b60c084015260e084013591508082111561229557600080fd5b6122a18583860161214a565b60e0840152610100915081840135818111156122bc57600080fd5b6122c88682870161214a565b8385015250610120915081840135818111156122e357600080fd5b6122ef8682870161214a565b83850152506101409150818401358181111561230a57600080fd5b6123168682870161214a565b8385015250505092915050565b60006020828403121561233557600080fd5b813567ffffffffffffffff81111561234c57600080fd5b6114ff848285016121d8565b60006020828403121561236a57600080fd5b813567ffffffffffffffff81111561238157600080fd5b82016101608185031215611f6a57600080fd5b8015158114610f1957600080fd5b600080604083850312156123b557600080fd5b82356123c0816120ed565b915060208301356123d081612394565b809150509250929050565b600067ffffffffffffffff8211156123f5576123f5612045565b5060051b60200190565b600082601f83011261241057600080fd5b81356020612425612420836123db565b61209e565b82815260059290921b8401810191818101908684111561244457600080fd5b8286015b8481101561245f5780358352918301918301612448565b509695505050505050565b60008060006060848603121561247f57600080fd5b833561248a816120ed565b925060208481013567ffffffffffffffff808211156124a857600080fd5b818701915087601f8301126124bc57600080fd5b81356124ca612420826123db565b81815260059190911b8301840190848101908a8311156124e957600080fd5b938501935b82851015612510578435612501816120ed565b825293850193908501906124ee565b96505050604087013592508083111561252857600080fd5b5050612536868287016123ff565b9150509250925092565b60006020828403121561255257600080fd5b8135611f6a816120ed565b60006020828403121561256f57600080fd5b5035919050565b6000806000806060858703121561258c57600080fd5b8435612597816120ed565b935060208501359250604085013567ffffffffffffffff808211156125bb57600080fd5b818701915087601f8301126125cf57600080fd5b8135818111156125de57600080fd5b8860208285010111156125f057600080fd5b95989497505060200194505050565b60008060006060848603121561261457600080fd5b61261d84611f71565b925060208401356003811061263157600080fd5b915061263f60408501612136565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261267d57600080fd5b830160208101925035905067ffffffffffffffff81111561269d57600080fd5b8036038213156126ac57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815261272a602082016127108461210f565b73ffffffffffffffffffffffffffffffffffffffff169052565b60006127386020840161211a565b6bffffffffffffffffffffffff81166040840152506127596040840161210f565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061278260608401612136565b63ffffffff811660808401525061279b60808401611f71565b60ff811660a0840152506127b160a0840161210f565b73ffffffffffffffffffffffffffffffffffffffff811660c0840152506127db60c0840184612648565b6101608060e08601526127f3610180860183856126b3565b925061280260e0870187612648565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061010081888703018189015261283c8686856126b3565b955061284a818a018a612648565b95509250506101208188870301818901526128668686856126b3565b9550612874818a018a612648565b95509250506101408188870301818901526128908686856126b3565b955061289e818a018a612648565b955092505080878603018388015250611dff8484836126b3565b600061070a36836121d8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612953576129536128f3565b5060010190565b60ff84168152606081016129716020830185611fd1565b63ffffffff83166040830152949350505050565b60006020828403121561299757600080fd5b8151611f6a81612394565b602081526129c960208201835173ffffffffffffffffffffffffffffffffffffffff169052565b600060208301516129ea60408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612a6c610180850183611f0d565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610100818786030181880152612aaa8584611f0d565b945080880151925050610120818786030181880152612ac98584611f0d565b945080880151925050610140818786030181880152612ae88584611f0d565b908801518782039092018488015293509050612b048382611f0d565b9695505050505050565b6000610140808352612b228184018e611f0d565b90508281036020840152612b36818d611f0d565b905063ffffffff8b16604084015273ffffffffffffffffffffffffffffffffffffffff8a16606084015260ff8916608084015282810360a0840152612b7b8189611f0d565b905082810360c0840152612b8f8188611f0d565b905082810360e0840152612ba38187611f0d565b9150506bffffffffffffffffffffffff8416610100830152612bde61012083018473ffffffffffffffffffffffffffffffffffffffff169052565b9b9a5050505050505050505050565b600063ffffffff808316818103612c0657612c066128f3565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612c6781840187611f0d565b905082810360c0840152612c7b8186611f0d565b905082810360e0840152612bde8185611f0d565b600060208284031215612ca157600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612ceb6060830184611f0d565b95945050505050565b60008251612d06818460208701611ee9565b919091019291505056fea164736f6c6343000813000a", } var AutomationRegistrarABI = AutomationRegistrarMetaData.ABI @@ -1358,6 +1358,7 @@ type AutomationRegistrarRegistrationRequested struct { OffchainConfig []byte CheckData []byte Amount *big.Int + BillingToken common.Address Raw types.Log } @@ -1601,7 +1602,7 @@ func (AutomationRegistrarRegistrationRejected) Topic() common.Hash { } func (AutomationRegistrarRegistrationRequested) Topic() common.Hash { - return common.HexToHash("0x7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b7") + return common.HexToHash("0xd178af9fe30387562e61bb997b245b7f49c26aad1e50c39d7b438ffa6c41b306") } func (AutomationRegistrarTriggerConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go new file mode 100644 index 0000000000..e32d6890dd --- /dev/null +++ b/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3/automation_registry_logic_c_wrapper_2_3.go @@ -0,0 +1,7037 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package automation_registry_logic_c_wrapper_2_3 + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type AutomationRegistryBase23BillingConfig struct { + GasFeePPB uint32 + FlatFeeMilliCents *big.Int + PriceFeed common.Address + Decimals uint8 + FallbackPrice *big.Int + MinSpend *big.Int +} + +type AutomationRegistryBase23BillingOverrides struct { + GasFeePPB uint32 + FlatFeeMilliCents *big.Int +} + +type AutomationRegistryBase23HotVars struct { + TotalPremium *big.Int + LatestEpoch uint32 + StalenessSeconds *big.Int + GasCeilingMultiplier uint16 + F uint8 + Paused bool + ReentrancyGuard bool + ReorgProtectionEnabled bool + ChainModule common.Address +} + +type AutomationRegistryBase23OnchainConfig struct { + CheckGasLimit uint32 + MaxPerformGas uint32 + MaxCheckDataSize uint32 + Transcoder common.Address + ReorgProtectionEnabled bool + StalenessSeconds *big.Int + MaxPerformDataSize uint32 + MaxRevertDataSize uint32 + UpkeepPrivilegeManager common.Address + GasCeilingMultiplier uint16 + FinanceAdmin common.Address + FallbackGasPrice *big.Int + FallbackLinkPrice *big.Int + FallbackNativePrice *big.Int + Registrars []common.Address + ChainModule common.Address +} + +type AutomationRegistryBase23PaymentReceipt struct { + GasChargeInBillingToken *big.Int + PremiumInBillingToken *big.Int + GasReimbursementInJuels *big.Int + PremiumInJuels *big.Int + BillingToken common.Address + LinkUSD *big.Int + NativeUSD *big.Int + BillingUSD *big.Int +} + +type AutomationRegistryBase23Storage struct { + Transcoder common.Address + CheckGasLimit uint32 + MaxPerformGas uint32 + Nonce uint32 + UpkeepPrivilegeManager common.Address + ConfigCount uint32 + LatestConfigBlockNumber uint32 + MaxCheckDataSize uint32 + FinanceAdmin common.Address + MaxPerformDataSize uint32 + MaxRevertDataSize uint32 +} + +type AutomationRegistryBase23TransmitterPayeeInfo struct { + TransmitterAddress common.Address + PayeeAddress common.Address +} + +type IAutomationV21PlusCommonOnchainConfigLegacy struct { + PaymentPremiumPPB uint32 + FlatFeeMicroLink uint32 + CheckGasLimit uint32 + StalenessSeconds *big.Int + GasCeilingMultiplier uint16 + MinUpkeepSpend *big.Int + MaxPerformGas uint32 + MaxCheckDataSize uint32 + MaxPerformDataSize uint32 + MaxRevertDataSize uint32 + FallbackGasPrice *big.Int + FallbackLinkPrice *big.Int + Transcoder common.Address + Registrars []common.Address + UpkeepPrivilegeManager common.Address +} + +type IAutomationV21PlusCommonStateLegacy struct { + Nonce uint32 + OwnerLinkBalance *big.Int + ExpectedLinkBalance *big.Int + TotalPremium *big.Int + NumUpkeeps *big.Int + ConfigCount uint32 + LatestConfigBlockNumber uint32 + LatestConfigDigest [32]byte + LatestEpoch uint32 + Paused bool +} + +type IAutomationV21PlusCommonUpkeepInfoLegacy struct { + Target common.Address + PerformGas uint32 + CheckData []byte + Balance *big.Int + Admin common.Address + MaxValidBlocknumber uint64 + LastPerformedBlockNumber uint32 + AmountSpent *big.Int + Paused bool + OffchainConfig []byte +} + +var AutomationRegistryLogicCMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkUSDFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeUSDFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"fastGasFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"automationForwarderLogic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowedReadOnlyAddress\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.PayoutMode\",\"name\":\"payoutMode\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"wrappedNativeTokenAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint96\",\"name\":\"gasChargeInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"gasReimbursementInJuels\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInJuels\",\"type\":\"uint96\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"linkUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"billingUSD\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.PaymentReceipt\",\"name\":\"receipt\",\"type\":\"tuple\"}],\"name\":\"UpkeepCharged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getAvailableERC20ForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverridesEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"contractIAutomationForwarder\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"enumAutomationRegistryBase2_3.PayoutMode\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"enumAutomationRegistryBase2_3.MigrationPermission\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.MigrationPermission\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101606040523480156200001257600080fd5b5060405162005c8738038062005c87833981016040819052620000359162000309565b87878787878787873380600081620000945760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c757620000c78162000241565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff191660018381811115620001185762000118620003b6565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000179573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019f9190620003cc565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002099190620003cc565b60ff16146200022b576040516301f86e1760e41b815260040160405180910390fd5b50505050505050505050505050505050620003f8565b336001600160a01b038216036200029b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200008b565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200030457600080fd5b919050565b600080600080600080600080610100898b0312156200032757600080fd5b6200033289620002ec565b97506200034260208a01620002ec565b96506200035260408a01620002ec565b95506200036260608a01620002ec565b94506200037260808a01620002ec565b93506200038260a08a01620002ec565b925060c0890151600281106200039757600080fd5b9150620003a760e08a01620002ec565b90509295985092959890939650565b634e487b7160e01b600052602160045260246000fd5b600060208284031215620003df57600080fd5b815160ff81168114620003f157600080fd5b9392505050565b60805160a05160c05160e051610100516101205161014051615803620004846000396000610b7001526000610ad2015260006107be0152600081816109a001526135b60152600081816109540152613e3201526000818161051d0152613690015260008181610c1801528181611df00152818161256b015281816125c80152613af601526158036000f3fe608060405234801561001057600080fd5b50600436106103d05760003560e01c80638ed02bab116101ff578063c3f909d41161011a578063eb5dcd6c116100ad578063f5a418461161007c578063f5a4184614610eb4578063f777ff0614610f35578063faa3e99614610f3c578063ffd242bd14610f8257600080fd5b8063eb5dcd6c14610de5578063ec4de4ba14610df8578063ed56b3e114610e2e578063f2fde38b14610ea157600080fd5b8063d09dc339116100e9578063d09dc33914610c3c578063d763264814610c44578063d85aa07c14610c57578063e80a3d4414610c5f57600080fd5b8063c3f909d414610bd6578063c5b964e014610beb578063c7c3a19a14610bf6578063ca30e60314610c1657600080fd5b8063aab9edd611610192578063b3596c2311610161578063b3596c23146107e2578063b6511a2a14610ba7578063b657bc9c14610bae578063ba87666814610bc157600080fd5b8063aab9edd614610b57578063abc76ae014610b66578063ac4dc59a14610b6e578063b121e14714610b9457600080fd5b8063a08714c0116101ce578063a08714c014610ad0578063a538b2eb14610af6578063a710b22114610b3c578063a87f45fe14610b4f57600080fd5b80638ed02bab14610a5c5780639089daa414610a7a57806393f6ebcf14610a8f5780639e0a99ed14610ac857600080fd5b806343cc055c116102ef5780636209e1e91161028257806379ba50971161025157806379ba5097146109ea57806379ea9943146109f25780638456cb5914610a365780638da5cb5b14610a3e57600080fd5b80636209e1e91461098b5780636709d0e51461099e578063671d36ed146109c45780636eec02a2146109d757600080fd5b80635425d8ac116102be5780635425d8ac146107bc57806357359584146107e2578063614486af146109525780636181d82d1461097857600080fd5b806343cc055c1461074957806344cb70b8146107705780634ca16c52146107935780635147cd591461079c57600080fd5b8063207b6516116103675780633b9cce59116103365780633b9cce59146106c05780633f4ba83a146106d3578063421d183b146106db57806343b46e5f1461074157600080fd5b8063207b651614610508578063226cf83c1461051b578063232c1cc5146105625780633408f73a1461056957600080fd5b8063187256e8116103a3578063187256e81461043b57806319d97a941461044e5780631e0104391461046e5780631efcf646146104d057600080fd5b8063050ee65d146103d557806306e3b632146103ed5780630b7d33e61461040d5780631865c57d14610422575b600080fd5b6201de845b6040519081526020015b60405180910390f35b6104006103fb36600461447a565b610f8a565b6040516103e491906144d7565b61042061041b366004614533565b6110a7565b005b61042a611108565b6040516103e495949392919061472b565b61042061044936600461486c565b611508565b61046161045c3660046148a9565b611579565b6040516103e49190614926565b6104b361047c3660046148a9565b60009081526004602052604090206001015470010000000000000000000000000000000090046bffffffffffffffffffffffff1690565b6040516bffffffffffffffffffffffff90911681526020016103e4565b6104f86104de3660046148a9565b600090815260046020526040902054610100900460ff1690565b60405190151581526020016103e4565b6104616105163660046148a9565b61161b565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103e4565b60186103da565b6106b36040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915250604080516101608101825260165473ffffffffffffffffffffffffffffffffffffffff808216835263ffffffff740100000000000000000000000000000000000000008084048216602086015278010000000000000000000000000000000000000000000000008085048316968601969096527c010000000000000000000000000000000000000000000000000000000093849004821660608601526017548084166080870152818104831660a0870152868104831660c087015293909304811660e085015260185491821661010085015291810482166101208401529290920490911661014082015290565b6040516103e49190614939565b6104206106ce366004614a63565b611638565b61042061188e565b6106ee6106e9366004614ad8565b6118f4565b60408051951515865260ff90941660208601526bffffffffffffffffffffffff9283169385019390935216606083015273ffffffffffffffffffffffffffffffffffffffff16608082015260a0016103e4565b610420611a13565b6014547801000000000000000000000000000000000000000000000000900460ff166104f8565b6104f861077e3660046148a9565b60009081526008602052604090205460ff1690565b62017f986103da565b6107af6107aa3660046148a9565b611eaa565b6040516103e49190614b34565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6108d46107f0366004614ad8565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525073ffffffffffffffffffffffffffffffffffffffff908116600090815260226020908152604091829020825160c081018452815463ffffffff81168252640100000000810462ffffff16938201939093526701000000000000008304909416928401929092527b01000000000000000000000000000000000000000000000000000000900460ff16606083015260018101546080830152600201546bffffffffffffffffffffffff1660a082015290565b6040516103e49190600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104b3610986366004614b47565b611eb5565b610461610999366004614ad8565b612010565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104206109d2366004614ba7565b612043565b6103da6109e5366004614ad8565b6120c3565b61042061216d565b61053d610a003660046148a9565b6000908152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61042061226f565b60005473ffffffffffffffffffffffffffffffffffffffff1661053d565b60155473ffffffffffffffffffffffffffffffffffffffff1661053d565b610a826122e8565b6040516103e49190614be3565b61053d610a9d3660046148a9565b60009081526004602052604090206002015473ffffffffffffffffffffffffffffffffffffffff1690565b6103a46103da565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6104f8610b04366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260226020526040902054670100000000000000900416151590565b610420610b4a366004614c4c565b6123fa565b610420612728565b604051600481526020016103e4565b6115e06103da565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b610420610ba2366004614ad8565b61275a565b60326103da565b6104b3610bbc3660046148a9565b612852565b610bc9612979565b6040516103e49190614c7a565b610bde6129e8565b6040516103e49190614cd4565b60255460ff166107af565b610c09610c043660046148a9565b612bd0565b6040516103e49190614e5b565b7f000000000000000000000000000000000000000000000000000000000000000061053d565b6103da612fe0565b6104b3610c523660046148a9565b612fef565b601b546103da565b610dd86040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091525060408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff750100000000000000000000000000000000000000000083048116608083015276010000000000000000000000000000000000000000000083048116151560a08301527701000000000000000000000000000000000000000000000083048116151560c08301527801000000000000000000000000000000000000000000000000909204909116151560e082015260155473ffffffffffffffffffffffffffffffffffffffff1661010082015290565b6040516103e49190614f92565b610420610df3366004614c4c565b612ffa565b6103da610e06366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205490565b610e88610e3c366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602090815260409182902082518084019093525460ff8082161515808552610100909204169290910182905291565b60408051921515835260ff9091166020830152016103e4565b610420610eaf366004614ad8565b613159565b610f0f610ec23660046148a9565b60408051808201909152600080825260208201525060009081526023602090815260409182902082518084019093525463ffffffff81168352640100000000900462ffffff169082015290565b60408051825163ffffffff16815260209283015162ffffff1692810192909252016103e4565b60406103da565b610f75610f4a366004614ad8565b73ffffffffffffffffffffffffffffffffffffffff166000908152601c602052604090205460ff1690565b6040516103e49190615062565b6103da61316d565b60606000610f986002613175565b9050808410610fd3576040517f1390f2a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610fdf84866150a5565b905081811180610fed575083155b610ff75780610ff9565b815b9050600061100786836150b8565b67ffffffffffffffff81111561101f5761101f6150cb565b604051908082528060200260200182016040528015611048578160200160208202803683370190505b50905060005b815181101561109b5761106c61106488836150a5565b60029061317f565b82828151811061107e5761107e6150fa565b60209081029190910101528061109381615129565b91505061104e565b50925050505b92915050565b6110af61318b565b6000838152601f602052604090206110c8828483615203565b50827f2fd8d70753a007014349d4591843cc031c2dd7a260d7dd82eca8253686ae776983836040516110fb92919061531e565b60405180910390a2505050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810191909152604080516101e08101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a08201526101c081019190915260408051610140810182526016547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1681526000602082018190529181018290526014546bffffffffffffffffffffffff16606080830191909152918291608081016112416002613175565b81526017547401000000000000000000000000000000000000000080820463ffffffff908116602080860191909152780100000000000000000000000000000000000000000000000080850483166040808801919091526013546060808901919091526014546c01000000000000000000000000810486166080808b0191909152760100000000000000000000000000000000000000000000820460ff16151560a09a8b015283516101e0810185526000808252968101879052601654898104891695820195909552700100000000000000000000000000000000830462ffffff169381019390935273010000000000000000000000000000000000000090910461ffff169082015296870192909252808204831660c08701527c0100000000000000000000000000000000000000000000000000000000909404821660e086015260185492830482166101008601529290910416610120830152601954610140830152601a5461016083015273ffffffffffffffffffffffffffffffffffffffff166101808201529095506101a081016113dc60096131de565b815260175473ffffffffffffffffffffffffffffffffffffffff16602091820152601454600d80546040805182860281018601909152818152949850899489949293600e93750100000000000000000000000000000000000000000090910460ff1692859183018282801561148757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161145c575b50505050509250818054806020026020016040519081016040528092919081815260200182805480156114f057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116114c5575b50505050509150945094509450945094509091929394565b6115106131eb565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601c6020526040902080548291907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561157057611570614af5565b02179055505050565b6000818152601f6020526040902080546060919061159690615161565b80601f01602080910402602001604051908101604052809291908181526020018280546115c290615161565b801561160f5780601f106115e45761010080835404028352916020019161160f565b820191906000526020600020905b8154815290600101906020018083116115f257829003601f168201915b50505050509050919050565b6000818152601d6020526040902080546060919061159690615161565b6116406131eb565b600e54811461167b576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b600e5481101561184d576000600e828154811061169d5761169d6150fa565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526011909252604083205491935016908585858181106116e7576116e76150fa565b90506020020160208101906116fc9190614ad8565b905073ffffffffffffffffffffffffffffffffffffffff8116158061178f575073ffffffffffffffffffffffffffffffffffffffff82161580159061176d57508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561178f575073ffffffffffffffffffffffffffffffffffffffff81811614155b156117c6576040517fb387a23800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff818116146118375773ffffffffffffffffffffffffffffffffffffffff838116600090815260116020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169183169190911790555b505050808061184590615129565b91505061167e565b507fa46de38886467c59be07a0675f14781206a5477d871628af46c2443822fcb725600e83836040516118829392919061536b565b60405180910390a15050565b6118966131eb565b601480547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff1690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e0100000000000000000000000000009004909116606082015282918291829182919082906119ba5760608201516014546000916119a6916bffffffffffffffffffffffff1661541d565b600e549091506119b69082615471565b9150505b8151602083015160408401516119d190849061549c565b6060949094015173ffffffffffffffffffffffffffffffffffffffff9a8b16600090815260116020526040902054929b919a9499509750921694509092505050565b611a1b61326c565b600060255460ff166001811115611a3457611a34614af5565b03611a6b576040517fe0262d7400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600e546bffffffffffffffffffffffff909116906000611a8e600f613175565b90506000611a9c82846150a5565b905060008167ffffffffffffffff811115611ab957611ab96150cb565b604051908082528060200260200182016040528015611ae2578160200160208202803683370190505b50905060008267ffffffffffffffff811115611b0057611b006150cb565b604051908082528060200260200182016040528015611b29578160200160208202803683370190505b50905060005b85811015611c5b576000600e8281548110611b4c57611b4c6150fa565b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff169150611b7a828a8a6132bd565b9050806bffffffffffffffffffffffff16858481518110611b9d57611b9d6150fa565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff808416600090815260119092526040909120548551911690859085908110611beb57611beb6150fa565b73ffffffffffffffffffffffffffffffffffffffff92831660209182029290920181019190915292166000908152600b909252506040902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905580611c5381615129565b915050611b2f565b5060005b84811015611dd8576000611c74600f8361317f565b73ffffffffffffffffffffffffffffffffffffffff8082166000818152600b602090815260408083208151608081018352905460ff80821615158352610100820416828501526bffffffffffffffffffffffff6201000082048116838501526e0100000000000000000000000000009091041660608201529383526011909152902054929350911684611d078a866150a5565b81518110611d1757611d176150fa565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260408101516bffffffffffffffffffffffff1685611d5a8a866150a5565b81518110611d6a57611d6a6150fa565b60209081029190910181019190915273ffffffffffffffffffffffffffffffffffffffff9092166000908152600b909252506040902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff16905580611dd081615129565b915050611c5f565b5073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166000908152602160205260408120819055611e2b600f613175565b90505b8015611e6857611e55611e4d611e456001846150b8565b600f9061317f565b600f906134c5565b5080611e60816154c1565b915050611e2e565b507f5af23b715253628d12b660b27a4f3fc626562ea8a55040aa99ab3dc178989fad8183604051611e9a9291906154f6565b60405180910390a1505050505050565b60006110a1826134e7565b60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff750100000000000000000000000000000000000000000083048116608083015276010000000000000000000000000000000000000000000083048116151560a08301527701000000000000000000000000000000000000000000000083048116151560c08301527801000000000000000000000000000000000000000000000000909204909116151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152600090818080611fed84613592565b92509250925061200389858a8a8787878d613784565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080526040902080546060919061159690615161565b61204b61318b565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602080526040902061207a828483615203565b508273ffffffffffffffffffffffffffffffffffffffff167f7c44b4eb59ee7873514e7e43e7718c269d872965938b288aa143befca62f99d283836040516110fb92919061531e565b73ffffffffffffffffffffffffffffffffffffffff81166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa15801561213f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121639190615524565b6110a191906150b8565b60015473ffffffffffffffffffffffffffffffffffffffff1633146121f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6122776131eb565b601480547fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff167601000000000000000000000000000000000000000000001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016118ea565b600e5460609060008167ffffffffffffffff811115612309576123096150cb565b60405190808252806020026020018201604052801561234e57816020015b60408051808201909152600080825260208201528152602001906001900390816123275790505b50905060005b828110156123f3576000600e8281548110612371576123716150fa565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168084526011835260409384902054845180860190955281855290911691830182905285519093509091908590859081106123d3576123d36150fa565b6020026020010181905250505080806123eb90615129565b915050612354565b5092915050565b73ffffffffffffffffffffffffffffffffffffffff8116612447576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160255460ff16600181111561246057612460614af5565b03612497576040517f4a3578fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601160205260409020541633146124f7576040517fcebf515b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600e5460009161251a9185916bffffffffffffffffffffffff16906132bd565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600b6020908152604080832080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff1690557f000000000000000000000000000000000000000000000000000000000000000090931682526021905220549091506125b1906bffffffffffffffffffffffff8316906150b8565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166000818152602160205260408082209490945592517fa9059cbb00000000000000000000000000000000000000000000000000000000815291851660048301526bffffffffffffffffffffffff841660248301529063a9059cbb906044016020604051808303816000875af1158015612666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268a919061553d565b9050806126c3576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405133815273ffffffffffffffffffffffffffffffffffffffff808516916bffffffffffffffffffffffff8516918716907f9819093176a1851202c7bcfa46845809b4e47c261866550e94ed3775d2f406989060200160405180910390a450505050565b6127306131eb565b602580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152601260205260409020541633146127ba576040517f6752e7aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81811660008181526011602090815260408083208054337fffffffffffffffffffffffff000000000000000000000000000000000000000080831682179093556012909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915261297283612962816134e7565b8360400151846101000151611eb5565b9392505050565b606060248054806020026020016040519081016040528092919081815260200182805480156129de57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116129b3575b5050505050905090565b604080516102008101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201839052610160820183905261018082018390526101a082018390526101c08201526101e0810191909152604080516102008101825260165463ffffffff74010000000000000000000000000000000000000000808304821684527801000000000000000000000000000000000000000000000000808404831660208601526017547c0100000000000000000000000000000000000000000000000000000000810484169686019690965273ffffffffffffffffffffffffffffffffffffffff938416606086015260145460ff828204161515608087015262ffffff70010000000000000000000000000000000082041660a0870152601854928304841660c087015290820490921660e085015293821661010084015261ffff7301000000000000000000000000000000000000009091041661012083015291909116610140820152601954610160820152601a54610180820152601b546101a08201526101c08101612baa60096131de565b815260155473ffffffffffffffffffffffffffffffffffffffff16602090910152919050565b604080516101408101825260008082526020820181905260609282018390528282018190526080820181905260a0820181905260c0820181905260e082018190526101008201526101208101919091526000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a010000000000000000000090910481166080830181905260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c0100000000000000000000000000000000000000000000000000000000900490941660e08301526002909201549091169281019290925290919015612da557816080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da0919061555f565b612da8565b60005b90506040518061014001604052808273ffffffffffffffffffffffffffffffffffffffff168152602001836040015163ffffffff168152602001600760008781526020019081526020016000208054612e0090615161565b80601f0160208091040260200160405190810160405280929190818152602001828054612e2c90615161565b8015612e795780601f10612e4e57610100808354040283529160200191612e79565b820191906000526020600020905b815481529060010190602001808311612e5c57829003601f168201915b505050505081526020018360c001516bffffffffffffffffffffffff1681526020016005600087815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001836060015163ffffffff1667ffffffffffffffff1681526020018360e0015163ffffffff1681526020018360a001516bffffffffffffffffffffffff168152602001836000015115158152602001601e60008781526020019081526020016000208054612f5690615161565b80601f0160208091040260200160405190810160405280929190818152602001828054612f8290615161565b8015612fcf5780601f10612fa457610100808354040283529160200191612fcf565b820191906000526020600020905b815481529060010190602001808311612fb257829003601f168201915b505050505081525092505050919050565b6000612fea613af4565b905090565b60006110a182612852565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526011602052604090205416331461305a576040517fcebf515b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216036130a9576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152601260205260409020548116908216146131555773ffffffffffffffffffffffffffffffffffffffff82811660008181526012602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169486169485179055513392917f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836791a45b5050565b6131616131eb565b61316a81613bbe565b50565b6000612fea60025b60006110a1825490565b60006129728383613cb3565b60175473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6060600061297283613cdd565b60005473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016121ea565b60185473ffffffffffffffffffffffffffffffffffffffff1633146131dc576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134b9576000816060015185613355919061541d565b905060006133638583615471565b90508083604001818151613377919061549c565b6bffffffffffffffffffffffff16905250613392858261557c565b836060018181516133a3919061549c565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60006129728373ffffffffffffffffffffffffffffffffffffffff8416613d38565b6000818160045b600f811015613574577fff00000000000000000000000000000000000000000000000000000000000000821683826020811061352c5761352c6150fa565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461356257506000949350505050565b8061356c81615129565b9150506134ee565b5081600f1a600181111561358a5761358a614af5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561361f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364391906155c3565b509450909250505060008113158061365a57508142105b8061367b575082801561367b575061367282426150b8565b8463ffffffff16105b1561368a57601954965061368e565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156136f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371d91906155c3565b509450909250505060008113158061373457508142105b806137555750828015613755575061374c82426150b8565b8463ffffffff16105b1561376457601a549550613768565b8095505b86866137738a613e2b565b965096509650505050509193909250565b600080808089600181111561379b5761379b614af5565b036137aa575062017f986137ff565b60018960018111156137be576137be614af5565b036137cd57506201de846137ff565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016138129190615613565b6138209060ff16604061562c565b60185461384e906103a49074010000000000000000000000000000000000000000900463ffffffff166150a5565b61385891906150a5565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156138c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ed9190615643565b909250905081836138ff8360186150a5565b613909919061562c565b60808f0151613919906001615613565b6139289060ff166115e061562c565b61393291906150a5565b61393c91906150a5565b61394690856150a5565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156139b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139dd9190615524565b8d6060015161ffff166139f0919061562c565b94505050506000613a018b86613f15565b60008d815260046020526040902054909150610100900460ff1615613a665760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b6000613ad08c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250614091565b60208101518151919250613ae39161549c565b9d9c50505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015613b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bb49190615524565b612fea9190615667565b3373ffffffffffffffffffffffffffffffffffffffff821603613c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016121ea565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613cca57613cca6150fa565b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561160f57602002820191906000526020600020905b815481526020019060010190808311613d195750505050509050919050565b60008181526001830160205260408120548015613e21576000613d5c6001836150b8565b8554909150600090613d70906001906150b8565b9050818114613dd5576000866000018281548110613d9057613d906150fa565b9060005260206000200154905080876000018481548110613db357613db36150fa565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613de657613de6615687565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506110a1565b60009150506110a1565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613e9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ebf91906155c3565b50935050925050600082131580613ed557508042105b80613f0557506000846040015162ffffff16118015613f055750613ef981426150b8565b846040015162ffffff16105b156123f3575050601b5492915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015614002573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061402691906155c3565b5093505092505060008213158061403c57508042105b8061406c57506000866040015162ffffff1611801561406c575061406081426150b8565b866040015162ffffff16105b156140805760018301546060850152614088565b606084018290525b50505092915050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516140fc919061562c565b9050836101000151801561410f5750803a105b1561411757503a5b60006012831161412857600161413e565b6141336012846150b8565b61413e90600a6157d6565b9050600060128410614151576001614167565b61415c8460126150b8565b61416790600a6157d6565b905060008660a0015187604001518860200151896000015161418991906150a5565b614193908761562c565b61419d91906150a5565b6141a7919061562c565b9050614203828860e00151606001516141c0919061562c565b6001848a60e00151606001516141d6919061562c565b6141e091906150b8565b6141ea868561562c565b6141f491906150a5565b6141fe91906157e2565b6143d8565b6bffffffffffffffffffffffff1686526080870151614226906141fe90836157e2565b6bffffffffffffffffffffffff1660408088019190915260e0880151015160009061425f9062ffffff16683635c9adc5dea0000061562c565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b614292919061562c565b61429c91906150a5565b6142a6919061562c565b6142b0919061562c565b6142ba91906157e2565b6142c491906150a5565b9050614307848a60e00151606001516142dd919061562c565b6001868c60e00151606001516142f3919061562c565b6142fd91906150b8565b6141ea888561562c565b6bffffffffffffffffffffffff166020890152608089015161432d906141fe90836157e2565b6bffffffffffffffffffffffff16606089015260c089015173ffffffffffffffffffffffffffffffffffffffff166080808a0191909152890151614370906143d8565b6bffffffffffffffffffffffff1660a0808a0191909152890151614393906143d8565b6bffffffffffffffffffffffff1660c089015260e0890151606001516143b8906143d8565b6bffffffffffffffffffffffff1660e08901525050505050505092915050565b60006bffffffffffffffffffffffff821115614476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016121ea565b5090565b6000806040838503121561448d57600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b838110156144cc578151875295820195908201906001016144b0565b509495945050505050565b602081526000612972602083018461449c565b60008083601f8401126144fc57600080fd5b50813567ffffffffffffffff81111561451457600080fd5b60208301915083602082850101111561452c57600080fd5b9250929050565b60008060006040848603121561454857600080fd5b83359250602084013567ffffffffffffffff81111561456657600080fd5b614572868287016144ea565b9497909650939450505050565b600081518084526020808501945080840160005b838110156144cc57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614593565b805163ffffffff16825260006101e060208301516145eb602086018263ffffffff169052565b506040830151614603604086018263ffffffff169052565b50606083015161461a606086018262ffffff169052565b506080830151614630608086018261ffff169052565b5060a083015161465060a08601826bffffffffffffffffffffffff169052565b5060c083015161466860c086018263ffffffff169052565b5060e083015161468060e086018263ffffffff169052565b506101008381015163ffffffff908116918601919091526101208085015190911690850152610140808401519085015261016080840151908501526101808084015173ffffffffffffffffffffffffffffffffffffffff16908501526101a0808401518186018390526146f58387018261457f565b925050506101c0808401516147218287018273ffffffffffffffffffffffffffffffffffffffff169052565b5090949350505050565b855163ffffffff16815260006101c0602088015161475960208501826bffffffffffffffffffffffff169052565b5060408801516040840152606088015161478360608501826bffffffffffffffffffffffff169052565b506080880151608084015260a08801516147a560a085018263ffffffff169052565b5060c08801516147bd60c085018263ffffffff169052565b5060e088015160e0840152610100808901516147e08286018263ffffffff169052565b5050610120888101511515908401526101408301819052614803818401886145c5565b9050828103610160840152614818818761457f565b905082810361018084015261482d818661457f565b9150506148406101a083018460ff169052565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461316a57600080fd5b6000806040838503121561487f57600080fd5b823561488a8161484a565b915060208301356004811061489e57600080fd5b809150509250929050565b6000602082840312156148bb57600080fd5b5035919050565b6000815180845260005b818110156148e8576020818501810151868301820152016148cc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061297260208301846148c2565b815173ffffffffffffffffffffffffffffffffffffffff1681526101608101602083015161496f602084018263ffffffff169052565b506040830151614987604084018263ffffffff169052565b50606083015161499f606084018263ffffffff169052565b5060808301516149c7608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08301516149df60a084018263ffffffff169052565b5060c08301516149f760c084018263ffffffff169052565b5060e0830151614a0f60e084018263ffffffff169052565b506101008381015173ffffffffffffffffffffffffffffffffffffffff81168483015250506101208381015163ffffffff81168483015250506101408381015163ffffffff8116848301525b505092915050565b60008060208385031215614a7657600080fd5b823567ffffffffffffffff80821115614a8e57600080fd5b818501915085601f830112614aa257600080fd5b813581811115614ab157600080fd5b8660208260051b8501011115614ac657600080fd5b60209290920196919550909350505050565b600060208284031215614aea57600080fd5b81356129728161484a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061316a5761316a614af5565b60208101614b4183614b24565b91905290565b60008060008060808587031215614b5d57600080fd5b84359350602085013560028110614b7357600080fd5b9250604085013563ffffffff81168114614b8c57600080fd5b91506060850135614b9c8161484a565b939692955090935050565b600080600060408486031215614bbc57600080fd5b8335614bc78161484a565b9250602084013567ffffffffffffffff81111561456657600080fd5b602080825282518282018190526000919060409081850190868401855b82811015614c3f578151805173ffffffffffffffffffffffffffffffffffffffff90811686529087015116868501529284019290850190600101614c00565b5091979650505050505050565b60008060408385031215614c5f57600080fd5b8235614c6a8161484a565b9150602083013561489e8161484a565b6020808252825182820181905260009190848201906040850190845b81811015614cc857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614c96565b50909695505050505050565b60208152614ceb60208201835163ffffffff169052565b60006020830151614d04604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e0830151610100614d838185018363ffffffff169052565b8401519050610120614dac8482018373ffffffffffffffffffffffffffffffffffffffff169052565b8401519050610140614dc38482018361ffff169052565b8401519050610160614dec8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e080860182905291925090614e3461022086018461457f565b9086015173ffffffffffffffffffffffffffffffffffffffff811683870152909250614721565b60208152614e8260208201835173ffffffffffffffffffffffffffffffffffffffff169052565b60006020830151614e9b604084018263ffffffff169052565b506040830151610140806060850152614eb86101608501836148c2565b91506060850151614ed960808601826bffffffffffffffffffffffff169052565b50608085015173ffffffffffffffffffffffffffffffffffffffff811660a08601525060a085015167ffffffffffffffff811660c08601525060c085015163ffffffff811660e08601525060e0850151610100614f45818701836bffffffffffffffffffffffff169052565b8601519050610120614f5a8682018315159052565b8601518584037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00183870152905061484083826148c2565b6000610120820190506bffffffffffffffffffffffff835116825263ffffffff60208401511660208301526040830151614fd3604084018262ffffff169052565b506060830151614fe9606084018261ffff169052565b506080830151614ffe608084018260ff169052565b5060a083015161501260a084018215159052565b5060c083015161502660c084018215159052565b5060e083015161503a60e084018215159052565b506101008381015173ffffffffffffffffffffffffffffffffffffffff811684830152614a5b565b6020810160048310614b4157614b41614af5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156110a1576110a1615076565b818103818111156110a1576110a1615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361515a5761515a615076565b5060010190565b600181811c9082168061517557607f821691505b6020821081036151ae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156151fe57600081815260208120601f850160051c810160208610156151db5750805b601f850160051c820191505b818110156151fa578281556001016151e7565b5050505b505050565b67ffffffffffffffff83111561521b5761521b6150cb565b61522f836152298354615161565b836151b4565b6000601f841160018114615281576000851561524b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355615317565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156152d057868501358255602094850194600190920191016152b0565b508682101561530b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b6000604082016040835280865480835260608501915087600052602092508260002060005b828110156153c257815473ffffffffffffffffffffffffffffffffffffffff1684529284019260019182019101615390565b505050838103828501528481528590820160005b868110156154115782356153e98161484a565b73ffffffffffffffffffffffffffffffffffffffff16825291830191908301906001016153d6565b50979650505050505050565b6bffffffffffffffffffffffff8281168282160390808211156123f3576123f3615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006bffffffffffffffffffffffff8084168061549057615490615442565b92169190910492915050565b6bffffffffffffffffffffffff8181168382160190808211156123f3576123f3615076565b6000816154d0576154d0615076565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b604081526000615509604083018561457f565b828103602084015261551b818561449c565b95945050505050565b60006020828403121561553657600080fd5b5051919050565b60006020828403121561554f57600080fd5b8151801515811461297257600080fd5b60006020828403121561557157600080fd5b81516129728161484a565b6bffffffffffffffffffffffff818116838216028082169190828114614a5b57614a5b615076565b805169ffffffffffffffffffff811681146155be57600080fd5b919050565b600080600080600060a086880312156155db57600080fd5b6155e4866155a4565b9450602086015193506040860151925060608601519150615607608087016155a4565b90509295509295909350565b60ff81811683821601908111156110a1576110a1615076565b80820281158282048414176110a1576110a1615076565b6000806040838503121561565657600080fd5b505080516020909101519092909150565b81810360008312801583831316838312821617156123f3576123f3615076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600181815b8085111561570f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156156f5576156f5615076565b8085161561570257918102915b93841c93908002906156bb565b509250929050565b600082615726575060016110a1565b81615733575060006110a1565b816001811461574957600281146157535761576f565b60019150506110a1565b60ff84111561576457615764615076565b50506001821b6110a1565b5060208310610133831016604e8410600b8410161715615792575081810a6110a1565b61579c83836156b6565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156157ce576157ce615076565b029392505050565b60006129728383615717565b6000826157f1576157f1615442565b50049056fea164736f6c6343000813000a", +} + +var AutomationRegistryLogicCABI = AutomationRegistryLogicCMetaData.ABI + +var AutomationRegistryLogicCBin = AutomationRegistryLogicCMetaData.Bin + +func DeployAutomationRegistryLogicC(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, linkUSDFeed common.Address, nativeUSDFeed common.Address, fastGasFeed common.Address, automationForwarderLogic common.Address, allowedReadOnlyAddress common.Address, payoutMode uint8, wrappedNativeTokenAddress common.Address) (common.Address, *types.Transaction, *AutomationRegistryLogicC, error) { + parsed, err := AutomationRegistryLogicCMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AutomationRegistryLogicCBin), backend, link, linkUSDFeed, nativeUSDFeed, fastGasFeed, automationForwarderLogic, allowedReadOnlyAddress, payoutMode, wrappedNativeTokenAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &AutomationRegistryLogicC{address: address, abi: *parsed, AutomationRegistryLogicCCaller: AutomationRegistryLogicCCaller{contract: contract}, AutomationRegistryLogicCTransactor: AutomationRegistryLogicCTransactor{contract: contract}, AutomationRegistryLogicCFilterer: AutomationRegistryLogicCFilterer{contract: contract}}, nil +} + +type AutomationRegistryLogicC struct { + address common.Address + abi abi.ABI + AutomationRegistryLogicCCaller + AutomationRegistryLogicCTransactor + AutomationRegistryLogicCFilterer +} + +type AutomationRegistryLogicCCaller struct { + contract *bind.BoundContract +} + +type AutomationRegistryLogicCTransactor struct { + contract *bind.BoundContract +} + +type AutomationRegistryLogicCFilterer struct { + contract *bind.BoundContract +} + +type AutomationRegistryLogicCSession struct { + Contract *AutomationRegistryLogicC + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type AutomationRegistryLogicCCallerSession struct { + Contract *AutomationRegistryLogicCCaller + CallOpts bind.CallOpts +} + +type AutomationRegistryLogicCTransactorSession struct { + Contract *AutomationRegistryLogicCTransactor + TransactOpts bind.TransactOpts +} + +type AutomationRegistryLogicCRaw struct { + Contract *AutomationRegistryLogicC +} + +type AutomationRegistryLogicCCallerRaw struct { + Contract *AutomationRegistryLogicCCaller +} + +type AutomationRegistryLogicCTransactorRaw struct { + Contract *AutomationRegistryLogicCTransactor +} + +func NewAutomationRegistryLogicC(address common.Address, backend bind.ContractBackend) (*AutomationRegistryLogicC, error) { + abi, err := abi.JSON(strings.NewReader(AutomationRegistryLogicCABI)) + if err != nil { + return nil, err + } + contract, err := bindAutomationRegistryLogicC(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicC{address: address, abi: abi, AutomationRegistryLogicCCaller: AutomationRegistryLogicCCaller{contract: contract}, AutomationRegistryLogicCTransactor: AutomationRegistryLogicCTransactor{contract: contract}, AutomationRegistryLogicCFilterer: AutomationRegistryLogicCFilterer{contract: contract}}, nil +} + +func NewAutomationRegistryLogicCCaller(address common.Address, caller bind.ContractCaller) (*AutomationRegistryLogicCCaller, error) { + contract, err := bindAutomationRegistryLogicC(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCCaller{contract: contract}, nil +} + +func NewAutomationRegistryLogicCTransactor(address common.Address, transactor bind.ContractTransactor) (*AutomationRegistryLogicCTransactor, error) { + contract, err := bindAutomationRegistryLogicC(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCTransactor{contract: contract}, nil +} + +func NewAutomationRegistryLogicCFilterer(address common.Address, filterer bind.ContractFilterer) (*AutomationRegistryLogicCFilterer, error) { + contract, err := bindAutomationRegistryLogicC(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCFilterer{contract: contract}, nil +} + +func bindAutomationRegistryLogicC(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AutomationRegistryLogicCMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AutomationRegistryLogicC.Contract.AutomationRegistryLogicCCaller.contract.Call(opts, result, method, params...) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.AutomationRegistryLogicCTransactor.contract.Transfer(opts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.AutomationRegistryLogicCTransactor.contract.Transact(opts, method, params...) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AutomationRegistryLogicC.Contract.contract.Call(opts, result, method, params...) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.contract.Transfer(opts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.contract.Transact(opts, method, params...) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetActiveUpkeepIDs(opts *bind.CallOpts, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getActiveUpkeepIDs", startIndex, maxCount) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetActiveUpkeepIDs(startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetActiveUpkeepIDs(&_AutomationRegistryLogicC.CallOpts, startIndex, maxCount) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetActiveUpkeepIDs(startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetActiveUpkeepIDs(&_AutomationRegistryLogicC.CallOpts, startIndex, maxCount) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetAdminPrivilegeConfig(opts *bind.CallOpts, admin common.Address) ([]byte, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getAdminPrivilegeConfig", admin) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetAdminPrivilegeConfig(admin common.Address) ([]byte, error) { + return _AutomationRegistryLogicC.Contract.GetAdminPrivilegeConfig(&_AutomationRegistryLogicC.CallOpts, admin) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetAdminPrivilegeConfig(admin common.Address) ([]byte, error) { + return _AutomationRegistryLogicC.Contract.GetAdminPrivilegeConfig(&_AutomationRegistryLogicC.CallOpts, admin) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetAllowedReadOnlyAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getAllowedReadOnlyAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetAllowedReadOnlyAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetAllowedReadOnlyAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetAllowedReadOnlyAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetAllowedReadOnlyAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetAutomationForwarderLogic(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getAutomationForwarderLogic") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetAutomationForwarderLogic() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetAutomationForwarderLogic(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetAutomationForwarderLogic() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetAutomationForwarderLogic(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetAvailableERC20ForPayment(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getAvailableERC20ForPayment", billingToken) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetAvailableERC20ForPayment(billingToken common.Address) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetAvailableERC20ForPayment(&_AutomationRegistryLogicC.CallOpts, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetAvailableERC20ForPayment(billingToken common.Address) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetAvailableERC20ForPayment(&_AutomationRegistryLogicC.CallOpts, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBalance", id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBalance(id *big.Int) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetBalance(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBalance(id *big.Int) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetBalance(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBillingConfig", billingToken) + + if err != nil { + return *new(AutomationRegistryBase23BillingConfig), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingConfig)).(*AutomationRegistryBase23BillingConfig) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBillingConfig(billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _AutomationRegistryLogicC.Contract.GetBillingConfig(&_AutomationRegistryLogicC.CallOpts, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBillingConfig(billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _AutomationRegistryLogicC.Contract.GetBillingConfig(&_AutomationRegistryLogicC.CallOpts, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBillingOverrides", upkeepID) + + if err != nil { + return *new(AutomationRegistryBase23BillingOverrides), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingOverrides)).(*AutomationRegistryBase23BillingOverrides) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBillingOverrides(upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + return _AutomationRegistryLogicC.Contract.GetBillingOverrides(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBillingOverrides(upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) { + return _AutomationRegistryLogicC.Contract.GetBillingOverrides(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBillingOverridesEnabled(opts *bind.CallOpts, upkeepID *big.Int) (bool, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBillingOverridesEnabled", upkeepID) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBillingOverridesEnabled(upkeepID *big.Int) (bool, error) { + return _AutomationRegistryLogicC.Contract.GetBillingOverridesEnabled(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBillingOverridesEnabled(upkeepID *big.Int) (bool, error) { + return _AutomationRegistryLogicC.Contract.GetBillingOverridesEnabled(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBillingToken", upkeepID) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBillingToken(upkeepID *big.Int) (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetBillingToken(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBillingToken(upkeepID *big.Int) (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetBillingToken(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBillingTokenConfig(opts *bind.CallOpts, token common.Address) (AutomationRegistryBase23BillingConfig, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBillingTokenConfig", token) + + if err != nil { + return *new(AutomationRegistryBase23BillingConfig), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23BillingConfig)).(*AutomationRegistryBase23BillingConfig) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBillingTokenConfig(token common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _AutomationRegistryLogicC.Contract.GetBillingTokenConfig(&_AutomationRegistryLogicC.CallOpts, token) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBillingTokenConfig(token common.Address) (AutomationRegistryBase23BillingConfig, error) { + return _AutomationRegistryLogicC.Contract.GetBillingTokenConfig(&_AutomationRegistryLogicC.CallOpts, token) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetBillingTokens(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getBillingTokens") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetBillingTokens() ([]common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetBillingTokens(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetBillingTokens() ([]common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetBillingTokens(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetCancellationDelay(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getCancellationDelay") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetCancellationDelay() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetCancellationDelay(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetCancellationDelay() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetCancellationDelay(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetChainModule(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getChainModule") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetChainModule() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetChainModule(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetChainModule() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetChainModule(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetConditionalGasOverhead(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getConditionalGasOverhead") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetConditionalGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetConditionalGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetConditionalGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetConditionalGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetConfig(opts *bind.CallOpts) (AutomationRegistryBase23OnchainConfig, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getConfig") + + if err != nil { + return *new(AutomationRegistryBase23OnchainConfig), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23OnchainConfig)).(*AutomationRegistryBase23OnchainConfig) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetConfig() (AutomationRegistryBase23OnchainConfig, error) { + return _AutomationRegistryLogicC.Contract.GetConfig(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetConfig() (AutomationRegistryBase23OnchainConfig, error) { + return _AutomationRegistryLogicC.Contract.GetConfig(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetFallbackNativePrice(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getFallbackNativePrice") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetFallbackNativePrice() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetFallbackNativePrice(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetFallbackNativePrice() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetFallbackNativePrice(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetFastGasFeedAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getFastGasFeedAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetFastGasFeedAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetFastGasFeedAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetFastGasFeedAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetFastGasFeedAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetForwarder(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getForwarder", upkeepID) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetForwarder(upkeepID *big.Int) (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetForwarder(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetForwarder(upkeepID *big.Int) (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetForwarder(&_AutomationRegistryLogicC.CallOpts, upkeepID) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetHotVars(opts *bind.CallOpts) (AutomationRegistryBase23HotVars, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getHotVars") + + if err != nil { + return *new(AutomationRegistryBase23HotVars), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23HotVars)).(*AutomationRegistryBase23HotVars) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetHotVars() (AutomationRegistryBase23HotVars, error) { + return _AutomationRegistryLogicC.Contract.GetHotVars(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetHotVars() (AutomationRegistryBase23HotVars, error) { + return _AutomationRegistryLogicC.Contract.GetHotVars(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetLinkAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getLinkAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetLinkAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetLinkAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetLinkAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetLinkAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetLinkUSDFeedAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getLinkUSDFeedAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetLinkUSDFeedAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetLinkUSDFeedAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetLinkUSDFeedAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetLinkUSDFeedAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetLogGasOverhead(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getLogGasOverhead") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetLogGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetLogGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetLogGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetLogGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetMaxPaymentForGas(opts *bind.CallOpts, id *big.Int, triggerType uint8, gasLimit uint32, billingToken common.Address) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getMaxPaymentForGas", id, triggerType, gasLimit, billingToken) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetMaxPaymentForGas(id *big.Int, triggerType uint8, gasLimit uint32, billingToken common.Address) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetMaxPaymentForGas(&_AutomationRegistryLogicC.CallOpts, id, triggerType, gasLimit, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetMaxPaymentForGas(id *big.Int, triggerType uint8, gasLimit uint32, billingToken common.Address) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetMaxPaymentForGas(&_AutomationRegistryLogicC.CallOpts, id, triggerType, gasLimit, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetMinBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getMinBalance", id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetMinBalance(id *big.Int) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetMinBalance(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetMinBalance(id *big.Int) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetMinBalance(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetMinBalanceForUpkeep(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getMinBalanceForUpkeep", id) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetMinBalanceForUpkeep(id *big.Int) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetMinBalanceForUpkeep(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetMinBalanceForUpkeep(id *big.Int) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetMinBalanceForUpkeep(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetNativeUSDFeedAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getNativeUSDFeedAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetNativeUSDFeedAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetNativeUSDFeedAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetNativeUSDFeedAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetNativeUSDFeedAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetNumUpkeeps(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getNumUpkeeps") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetNumUpkeeps() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetNumUpkeeps(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetNumUpkeeps() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetNumUpkeeps(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetPayoutMode(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getPayoutMode") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetPayoutMode() (uint8, error) { + return _AutomationRegistryLogicC.Contract.GetPayoutMode(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetPayoutMode() (uint8, error) { + return _AutomationRegistryLogicC.Contract.GetPayoutMode(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetPeerRegistryMigrationPermission(opts *bind.CallOpts, peer common.Address) (uint8, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getPeerRegistryMigrationPermission", peer) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetPeerRegistryMigrationPermission(peer common.Address) (uint8, error) { + return _AutomationRegistryLogicC.Contract.GetPeerRegistryMigrationPermission(&_AutomationRegistryLogicC.CallOpts, peer) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetPeerRegistryMigrationPermission(peer common.Address) (uint8, error) { + return _AutomationRegistryLogicC.Contract.GetPeerRegistryMigrationPermission(&_AutomationRegistryLogicC.CallOpts, peer) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetPerPerformByteGasOverhead(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getPerPerformByteGasOverhead") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetPerPerformByteGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetPerPerformByteGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetPerPerformByteGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetPerPerformByteGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetPerSignerGasOverhead(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getPerSignerGasOverhead") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetPerSignerGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetPerSignerGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetPerSignerGasOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetPerSignerGasOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetReorgProtectionEnabled(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getReorgProtectionEnabled") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetReorgProtectionEnabled() (bool, error) { + return _AutomationRegistryLogicC.Contract.GetReorgProtectionEnabled(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetReorgProtectionEnabled() (bool, error) { + return _AutomationRegistryLogicC.Contract.GetReorgProtectionEnabled(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetReserveAmount(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getReserveAmount", billingToken) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetReserveAmount(billingToken common.Address) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetReserveAmount(&_AutomationRegistryLogicC.CallOpts, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetReserveAmount(billingToken common.Address) (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetReserveAmount(&_AutomationRegistryLogicC.CallOpts, billingToken) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetSignerInfo(opts *bind.CallOpts, query common.Address) (GetSignerInfo, + + error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getSignerInfo", query) + + outstruct := new(GetSignerInfo) + if err != nil { + return *outstruct, err + } + + outstruct.Active = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.Index = *abi.ConvertType(out[1], new(uint8)).(*uint8) + + return *outstruct, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetSignerInfo(query common.Address) (GetSignerInfo, + + error) { + return _AutomationRegistryLogicC.Contract.GetSignerInfo(&_AutomationRegistryLogicC.CallOpts, query) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetSignerInfo(query common.Address) (GetSignerInfo, + + error) { + return _AutomationRegistryLogicC.Contract.GetSignerInfo(&_AutomationRegistryLogicC.CallOpts, query) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetState(opts *bind.CallOpts) (GetState, + + error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getState") + + outstruct := new(GetState) + if err != nil { + return *outstruct, err + } + + outstruct.State = *abi.ConvertType(out[0], new(IAutomationV21PlusCommonStateLegacy)).(*IAutomationV21PlusCommonStateLegacy) + outstruct.Config = *abi.ConvertType(out[1], new(IAutomationV21PlusCommonOnchainConfigLegacy)).(*IAutomationV21PlusCommonOnchainConfigLegacy) + outstruct.Signers = *abi.ConvertType(out[2], new([]common.Address)).(*[]common.Address) + outstruct.Transmitters = *abi.ConvertType(out[3], new([]common.Address)).(*[]common.Address) + outstruct.F = *abi.ConvertType(out[4], new(uint8)).(*uint8) + + return *outstruct, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetState() (GetState, + + error) { + return _AutomationRegistryLogicC.Contract.GetState(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetState() (GetState, + + error) { + return _AutomationRegistryLogicC.Contract.GetState(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetStorage(opts *bind.CallOpts) (AutomationRegistryBase23Storage, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getStorage") + + if err != nil { + return *new(AutomationRegistryBase23Storage), err + } + + out0 := *abi.ConvertType(out[0], new(AutomationRegistryBase23Storage)).(*AutomationRegistryBase23Storage) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetStorage() (AutomationRegistryBase23Storage, error) { + return _AutomationRegistryLogicC.Contract.GetStorage(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetStorage() (AutomationRegistryBase23Storage, error) { + return _AutomationRegistryLogicC.Contract.GetStorage(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetTransmitCalldataFixedBytesOverhead(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getTransmitCalldataFixedBytesOverhead") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetTransmitCalldataFixedBytesOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetTransmitCalldataFixedBytesOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetTransmitCalldataFixedBytesOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetTransmitCalldataFixedBytesOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetTransmitCalldataPerSignerBytesOverhead(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getTransmitCalldataPerSignerBytesOverhead") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetTransmitCalldataPerSignerBytesOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetTransmitCalldataPerSignerBytesOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetTransmitCalldataPerSignerBytesOverhead() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.GetTransmitCalldataPerSignerBytesOverhead(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetTransmitterInfo(opts *bind.CallOpts, query common.Address) (GetTransmitterInfo, + + error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getTransmitterInfo", query) + + outstruct := new(GetTransmitterInfo) + if err != nil { + return *outstruct, err + } + + outstruct.Active = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.Index = *abi.ConvertType(out[1], new(uint8)).(*uint8) + outstruct.Balance = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.LastCollected = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.Payee = *abi.ConvertType(out[4], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetTransmitterInfo(query common.Address) (GetTransmitterInfo, + + error) { + return _AutomationRegistryLogicC.Contract.GetTransmitterInfo(&_AutomationRegistryLogicC.CallOpts, query) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetTransmitterInfo(query common.Address) (GetTransmitterInfo, + + error) { + return _AutomationRegistryLogicC.Contract.GetTransmitterInfo(&_AutomationRegistryLogicC.CallOpts, query) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetTransmittersWithPayees(opts *bind.CallOpts) ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getTransmittersWithPayees") + + if err != nil { + return *new([]AutomationRegistryBase23TransmitterPayeeInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]AutomationRegistryBase23TransmitterPayeeInfo)).(*[]AutomationRegistryBase23TransmitterPayeeInfo) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetTransmittersWithPayees() ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + return _AutomationRegistryLogicC.Contract.GetTransmittersWithPayees(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetTransmittersWithPayees() ([]AutomationRegistryBase23TransmitterPayeeInfo, error) { + return _AutomationRegistryLogicC.Contract.GetTransmittersWithPayees(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetTriggerType(opts *bind.CallOpts, upkeepId *big.Int) (uint8, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getTriggerType", upkeepId) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetTriggerType(upkeepId *big.Int) (uint8, error) { + return _AutomationRegistryLogicC.Contract.GetTriggerType(&_AutomationRegistryLogicC.CallOpts, upkeepId) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetTriggerType(upkeepId *big.Int) (uint8, error) { + return _AutomationRegistryLogicC.Contract.GetTriggerType(&_AutomationRegistryLogicC.CallOpts, upkeepId) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetUpkeep(opts *bind.CallOpts, id *big.Int) (IAutomationV21PlusCommonUpkeepInfoLegacy, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getUpkeep", id) + + if err != nil { + return *new(IAutomationV21PlusCommonUpkeepInfoLegacy), err + } + + out0 := *abi.ConvertType(out[0], new(IAutomationV21PlusCommonUpkeepInfoLegacy)).(*IAutomationV21PlusCommonUpkeepInfoLegacy) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetUpkeep(id *big.Int) (IAutomationV21PlusCommonUpkeepInfoLegacy, error) { + return _AutomationRegistryLogicC.Contract.GetUpkeep(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetUpkeep(id *big.Int) (IAutomationV21PlusCommonUpkeepInfoLegacy, error) { + return _AutomationRegistryLogicC.Contract.GetUpkeep(&_AutomationRegistryLogicC.CallOpts, id) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetUpkeepPrivilegeConfig(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getUpkeepPrivilegeConfig", upkeepId) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) { + return _AutomationRegistryLogicC.Contract.GetUpkeepPrivilegeConfig(&_AutomationRegistryLogicC.CallOpts, upkeepId) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetUpkeepPrivilegeConfig(upkeepId *big.Int) ([]byte, error) { + return _AutomationRegistryLogicC.Contract.GetUpkeepPrivilegeConfig(&_AutomationRegistryLogicC.CallOpts, upkeepId) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetUpkeepTriggerConfig(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getUpkeepTriggerConfig", upkeepId) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetUpkeepTriggerConfig(upkeepId *big.Int) ([]byte, error) { + return _AutomationRegistryLogicC.Contract.GetUpkeepTriggerConfig(&_AutomationRegistryLogicC.CallOpts, upkeepId) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetUpkeepTriggerConfig(upkeepId *big.Int) ([]byte, error) { + return _AutomationRegistryLogicC.Contract.GetUpkeepTriggerConfig(&_AutomationRegistryLogicC.CallOpts, upkeepId) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) GetWrappedNativeTokenAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "getWrappedNativeTokenAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) GetWrappedNativeTokenAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetWrappedNativeTokenAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) GetWrappedNativeTokenAddress() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.GetWrappedNativeTokenAddress(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) HasDedupKey(opts *bind.CallOpts, dedupKey [32]byte) (bool, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "hasDedupKey", dedupKey) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) HasDedupKey(dedupKey [32]byte) (bool, error) { + return _AutomationRegistryLogicC.Contract.HasDedupKey(&_AutomationRegistryLogicC.CallOpts, dedupKey) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) HasDedupKey(dedupKey [32]byte) (bool, error) { + return _AutomationRegistryLogicC.Contract.HasDedupKey(&_AutomationRegistryLogicC.CallOpts, dedupKey) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "linkAvailableForPayment") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) LinkAvailableForPayment() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.LinkAvailableForPayment(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) LinkAvailableForPayment() (*big.Int, error) { + return _AutomationRegistryLogicC.Contract.LinkAvailableForPayment(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) Owner() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.Owner(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) Owner() (common.Address, error) { + return _AutomationRegistryLogicC.Contract.Owner(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) SupportsBillingToken(opts *bind.CallOpts, token common.Address) (bool, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "supportsBillingToken", token) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) SupportsBillingToken(token common.Address) (bool, error) { + return _AutomationRegistryLogicC.Contract.SupportsBillingToken(&_AutomationRegistryLogicC.CallOpts, token) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) SupportsBillingToken(token common.Address) (bool, error) { + return _AutomationRegistryLogicC.Contract.SupportsBillingToken(&_AutomationRegistryLogicC.CallOpts, token) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCaller) UpkeepVersion(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _AutomationRegistryLogicC.contract.Call(opts, &out, "upkeepVersion") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) UpkeepVersion() (uint8, error) { + return _AutomationRegistryLogicC.Contract.UpkeepVersion(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCCallerSession) UpkeepVersion() (uint8, error) { + return _AutomationRegistryLogicC.Contract.UpkeepVersion(&_AutomationRegistryLogicC.CallOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "acceptOwnership") +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) AcceptOwnership() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.AcceptOwnership(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.AcceptOwnership(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) AcceptPayeeship(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "acceptPayeeship", transmitter) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) AcceptPayeeship(transmitter common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.AcceptPayeeship(&_AutomationRegistryLogicC.TransactOpts, transmitter) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) AcceptPayeeship(transmitter common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.AcceptPayeeship(&_AutomationRegistryLogicC.TransactOpts, transmitter) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) DisableOffchainPayments(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "disableOffchainPayments") +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) DisableOffchainPayments() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.DisableOffchainPayments(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) DisableOffchainPayments() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.DisableOffchainPayments(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "pause") +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) Pause() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.Pause(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) Pause() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.Pause(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) SetAdminPrivilegeConfig(opts *bind.TransactOpts, admin common.Address, newPrivilegeConfig []byte) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "setAdminPrivilegeConfig", admin, newPrivilegeConfig) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) SetAdminPrivilegeConfig(admin common.Address, newPrivilegeConfig []byte) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetAdminPrivilegeConfig(&_AutomationRegistryLogicC.TransactOpts, admin, newPrivilegeConfig) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) SetAdminPrivilegeConfig(admin common.Address, newPrivilegeConfig []byte) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetAdminPrivilegeConfig(&_AutomationRegistryLogicC.TransactOpts, admin, newPrivilegeConfig) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) SetPayees(opts *bind.TransactOpts, payees []common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "setPayees", payees) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) SetPayees(payees []common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetPayees(&_AutomationRegistryLogicC.TransactOpts, payees) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) SetPayees(payees []common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetPayees(&_AutomationRegistryLogicC.TransactOpts, payees) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) SetPeerRegistryMigrationPermission(opts *bind.TransactOpts, peer common.Address, permission uint8) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "setPeerRegistryMigrationPermission", peer, permission) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) SetPeerRegistryMigrationPermission(peer common.Address, permission uint8) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetPeerRegistryMigrationPermission(&_AutomationRegistryLogicC.TransactOpts, peer, permission) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) SetPeerRegistryMigrationPermission(peer common.Address, permission uint8) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetPeerRegistryMigrationPermission(&_AutomationRegistryLogicC.TransactOpts, peer, permission) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) SetUpkeepPrivilegeConfig(opts *bind.TransactOpts, upkeepId *big.Int, newPrivilegeConfig []byte) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "setUpkeepPrivilegeConfig", upkeepId, newPrivilegeConfig) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) SetUpkeepPrivilegeConfig(upkeepId *big.Int, newPrivilegeConfig []byte) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetUpkeepPrivilegeConfig(&_AutomationRegistryLogicC.TransactOpts, upkeepId, newPrivilegeConfig) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) SetUpkeepPrivilegeConfig(upkeepId *big.Int, newPrivilegeConfig []byte) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SetUpkeepPrivilegeConfig(&_AutomationRegistryLogicC.TransactOpts, upkeepId, newPrivilegeConfig) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) SettleNOPsOffchain(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "settleNOPsOffchain") +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) SettleNOPsOffchain() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SettleNOPsOffchain(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) SettleNOPsOffchain() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.SettleNOPsOffchain(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "transferOwnership", to) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.TransferOwnership(&_AutomationRegistryLogicC.TransactOpts, to) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.TransferOwnership(&_AutomationRegistryLogicC.TransactOpts, to) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) TransferPayeeship(opts *bind.TransactOpts, transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "transferPayeeship", transmitter, proposed) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) TransferPayeeship(transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.TransferPayeeship(&_AutomationRegistryLogicC.TransactOpts, transmitter, proposed) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) TransferPayeeship(transmitter common.Address, proposed common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.TransferPayeeship(&_AutomationRegistryLogicC.TransactOpts, transmitter, proposed) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "unpause") +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) Unpause() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.Unpause(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) Unpause() (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.Unpause(&_AutomationRegistryLogicC.TransactOpts) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactor) WithdrawPayment(opts *bind.TransactOpts, from common.Address, to common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.contract.Transact(opts, "withdrawPayment", from, to) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCSession) WithdrawPayment(from common.Address, to common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.WithdrawPayment(&_AutomationRegistryLogicC.TransactOpts, from, to) +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCTransactorSession) WithdrawPayment(from common.Address, to common.Address) (*types.Transaction, error) { + return _AutomationRegistryLogicC.Contract.WithdrawPayment(&_AutomationRegistryLogicC.TransactOpts, from, to) +} + +type AutomationRegistryLogicCAdminPrivilegeConfigSetIterator struct { + Event *AutomationRegistryLogicCAdminPrivilegeConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCAdminPrivilegeConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCAdminPrivilegeConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCAdminPrivilegeConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCAdminPrivilegeConfigSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCAdminPrivilegeConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCAdminPrivilegeConfigSet struct { + Admin common.Address + PrivilegeConfig []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterAdminPrivilegeConfigSet(opts *bind.FilterOpts, admin []common.Address) (*AutomationRegistryLogicCAdminPrivilegeConfigSetIterator, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "AdminPrivilegeConfigSet", adminRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCAdminPrivilegeConfigSetIterator{contract: _AutomationRegistryLogicC.contract, event: "AdminPrivilegeConfigSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchAdminPrivilegeConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCAdminPrivilegeConfigSet, admin []common.Address) (event.Subscription, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "AdminPrivilegeConfigSet", adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCAdminPrivilegeConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "AdminPrivilegeConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseAdminPrivilegeConfigSet(log types.Log) (*AutomationRegistryLogicCAdminPrivilegeConfigSet, error) { + event := new(AutomationRegistryLogicCAdminPrivilegeConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "AdminPrivilegeConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCBillingConfigOverriddenIterator struct { + Event *AutomationRegistryLogicCBillingConfigOverridden + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCBillingConfigOverriddenIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCBillingConfigOverridden) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCBillingConfigOverridden) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCBillingConfigOverriddenIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCBillingConfigOverriddenIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCBillingConfigOverridden struct { + Id *big.Int + Overrides AutomationRegistryBase23BillingOverrides + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterBillingConfigOverridden(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCBillingConfigOverriddenIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "BillingConfigOverridden", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCBillingConfigOverriddenIterator{contract: _AutomationRegistryLogicC.contract, event: "BillingConfigOverridden", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchBillingConfigOverridden(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCBillingConfigOverridden, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "BillingConfigOverridden", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCBillingConfigOverridden) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "BillingConfigOverridden", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseBillingConfigOverridden(log types.Log) (*AutomationRegistryLogicCBillingConfigOverridden, error) { + event := new(AutomationRegistryLogicCBillingConfigOverridden) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "BillingConfigOverridden", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCBillingConfigOverrideRemovedIterator struct { + Event *AutomationRegistryLogicCBillingConfigOverrideRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCBillingConfigOverrideRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCBillingConfigOverrideRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCBillingConfigOverrideRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCBillingConfigOverrideRemovedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCBillingConfigOverrideRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCBillingConfigOverrideRemoved struct { + Id *big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterBillingConfigOverrideRemoved(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCBillingConfigOverrideRemovedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "BillingConfigOverrideRemoved", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCBillingConfigOverrideRemovedIterator{contract: _AutomationRegistryLogicC.contract, event: "BillingConfigOverrideRemoved", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchBillingConfigOverrideRemoved(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCBillingConfigOverrideRemoved, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "BillingConfigOverrideRemoved", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCBillingConfigOverrideRemoved) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "BillingConfigOverrideRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseBillingConfigOverrideRemoved(log types.Log) (*AutomationRegistryLogicCBillingConfigOverrideRemoved, error) { + event := new(AutomationRegistryLogicCBillingConfigOverrideRemoved) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "BillingConfigOverrideRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCBillingConfigSetIterator struct { + Event *AutomationRegistryLogicCBillingConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCBillingConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCBillingConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCBillingConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCBillingConfigSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCBillingConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCBillingConfigSet struct { + Token common.Address + Config AutomationRegistryBase23BillingConfig + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterBillingConfigSet(opts *bind.FilterOpts, token []common.Address) (*AutomationRegistryLogicCBillingConfigSetIterator, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "BillingConfigSet", tokenRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCBillingConfigSetIterator{contract: _AutomationRegistryLogicC.contract, event: "BillingConfigSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchBillingConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCBillingConfigSet, token []common.Address) (event.Subscription, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "BillingConfigSet", tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCBillingConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "BillingConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseBillingConfigSet(log types.Log) (*AutomationRegistryLogicCBillingConfigSet, error) { + event := new(AutomationRegistryLogicCBillingConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "BillingConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCCancelledUpkeepReportIterator struct { + Event *AutomationRegistryLogicCCancelledUpkeepReport + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCCancelledUpkeepReportIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCCancelledUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCCancelledUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCCancelledUpkeepReportIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCCancelledUpkeepReportIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCCancelledUpkeepReport struct { + Id *big.Int + Trigger []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterCancelledUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCCancelledUpkeepReportIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "CancelledUpkeepReport", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCCancelledUpkeepReportIterator{contract: _AutomationRegistryLogicC.contract, event: "CancelledUpkeepReport", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchCancelledUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCCancelledUpkeepReport, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "CancelledUpkeepReport", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCCancelledUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "CancelledUpkeepReport", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseCancelledUpkeepReport(log types.Log) (*AutomationRegistryLogicCCancelledUpkeepReport, error) { + event := new(AutomationRegistryLogicCCancelledUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "CancelledUpkeepReport", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCChainSpecificModuleUpdatedIterator struct { + Event *AutomationRegistryLogicCChainSpecificModuleUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCChainSpecificModuleUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCChainSpecificModuleUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCChainSpecificModuleUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCChainSpecificModuleUpdatedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCChainSpecificModuleUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCChainSpecificModuleUpdated struct { + NewModule common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterChainSpecificModuleUpdated(opts *bind.FilterOpts) (*AutomationRegistryLogicCChainSpecificModuleUpdatedIterator, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "ChainSpecificModuleUpdated") + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCChainSpecificModuleUpdatedIterator{contract: _AutomationRegistryLogicC.contract, event: "ChainSpecificModuleUpdated", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchChainSpecificModuleUpdated(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCChainSpecificModuleUpdated) (event.Subscription, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "ChainSpecificModuleUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCChainSpecificModuleUpdated) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "ChainSpecificModuleUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseChainSpecificModuleUpdated(log types.Log) (*AutomationRegistryLogicCChainSpecificModuleUpdated, error) { + event := new(AutomationRegistryLogicCChainSpecificModuleUpdated) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "ChainSpecificModuleUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCDedupKeyAddedIterator struct { + Event *AutomationRegistryLogicCDedupKeyAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCDedupKeyAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCDedupKeyAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCDedupKeyAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCDedupKeyAddedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCDedupKeyAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCDedupKeyAdded struct { + DedupKey [32]byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterDedupKeyAdded(opts *bind.FilterOpts, dedupKey [][32]byte) (*AutomationRegistryLogicCDedupKeyAddedIterator, error) { + + var dedupKeyRule []interface{} + for _, dedupKeyItem := range dedupKey { + dedupKeyRule = append(dedupKeyRule, dedupKeyItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "DedupKeyAdded", dedupKeyRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCDedupKeyAddedIterator{contract: _AutomationRegistryLogicC.contract, event: "DedupKeyAdded", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchDedupKeyAdded(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCDedupKeyAdded, dedupKey [][32]byte) (event.Subscription, error) { + + var dedupKeyRule []interface{} + for _, dedupKeyItem := range dedupKey { + dedupKeyRule = append(dedupKeyRule, dedupKeyItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "DedupKeyAdded", dedupKeyRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCDedupKeyAdded) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "DedupKeyAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseDedupKeyAdded(log types.Log) (*AutomationRegistryLogicCDedupKeyAdded, error) { + event := new(AutomationRegistryLogicCDedupKeyAdded) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "DedupKeyAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCFeesWithdrawnIterator struct { + Event *AutomationRegistryLogicCFeesWithdrawn + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCFeesWithdrawnIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCFeesWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCFeesWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCFeesWithdrawnIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCFeesWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCFeesWithdrawn struct { + AssetAddress common.Address + Recipient common.Address + Amount *big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryLogicCFeesWithdrawnIterator, error) { + + var assetAddressRule []interface{} + for _, assetAddressItem := range assetAddress { + assetAddressRule = append(assetAddressRule, assetAddressItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCFeesWithdrawnIterator{contract: _AutomationRegistryLogicC.contract, event: "FeesWithdrawn", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) { + + var assetAddressRule []interface{} + for _, assetAddressItem := range assetAddress { + assetAddressRule = append(assetAddressRule, assetAddressItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCFeesWithdrawn) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "FeesWithdrawn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseFeesWithdrawn(log types.Log) (*AutomationRegistryLogicCFeesWithdrawn, error) { + event := new(AutomationRegistryLogicCFeesWithdrawn) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "FeesWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCFundsAddedIterator struct { + Event *AutomationRegistryLogicCFundsAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCFundsAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCFundsAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCFundsAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCFundsAddedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCFundsAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCFundsAdded struct { + Id *big.Int + From common.Address + Amount *big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterFundsAdded(opts *bind.FilterOpts, id []*big.Int, from []common.Address) (*AutomationRegistryLogicCFundsAddedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "FundsAdded", idRule, fromRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCFundsAddedIterator{contract: _AutomationRegistryLogicC.contract, event: "FundsAdded", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchFundsAdded(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCFundsAdded, id []*big.Int, from []common.Address) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "FundsAdded", idRule, fromRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCFundsAdded) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "FundsAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseFundsAdded(log types.Log) (*AutomationRegistryLogicCFundsAdded, error) { + event := new(AutomationRegistryLogicCFundsAdded) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "FundsAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCFundsWithdrawnIterator struct { + Event *AutomationRegistryLogicCFundsWithdrawn + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCFundsWithdrawnIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCFundsWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCFundsWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCFundsWithdrawnIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCFundsWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCFundsWithdrawn struct { + Id *big.Int + Amount *big.Int + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterFundsWithdrawn(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCFundsWithdrawnIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "FundsWithdrawn", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCFundsWithdrawnIterator{contract: _AutomationRegistryLogicC.contract, event: "FundsWithdrawn", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCFundsWithdrawn, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "FundsWithdrawn", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCFundsWithdrawn) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseFundsWithdrawn(log types.Log) (*AutomationRegistryLogicCFundsWithdrawn, error) { + event := new(AutomationRegistryLogicCFundsWithdrawn) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator struct { + Event *AutomationRegistryLogicCInsufficientFundsUpkeepReport + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCInsufficientFundsUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCInsufficientFundsUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCInsufficientFundsUpkeepReport struct { + Id *big.Int + Trigger []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterInsufficientFundsUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "InsufficientFundsUpkeepReport", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator{contract: _AutomationRegistryLogicC.contract, event: "InsufficientFundsUpkeepReport", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchInsufficientFundsUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCInsufficientFundsUpkeepReport, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "InsufficientFundsUpkeepReport", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCInsufficientFundsUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "InsufficientFundsUpkeepReport", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseInsufficientFundsUpkeepReport(log types.Log) (*AutomationRegistryLogicCInsufficientFundsUpkeepReport, error) { + event := new(AutomationRegistryLogicCInsufficientFundsUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "InsufficientFundsUpkeepReport", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCNOPsSettledOffchainIterator struct { + Event *AutomationRegistryLogicCNOPsSettledOffchain + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCNOPsSettledOffchainIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCNOPsSettledOffchain) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCNOPsSettledOffchain) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCNOPsSettledOffchainIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCNOPsSettledOffchainIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCNOPsSettledOffchain struct { + Payees []common.Address + Payments []*big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterNOPsSettledOffchain(opts *bind.FilterOpts) (*AutomationRegistryLogicCNOPsSettledOffchainIterator, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "NOPsSettledOffchain") + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCNOPsSettledOffchainIterator{contract: _AutomationRegistryLogicC.contract, event: "NOPsSettledOffchain", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchNOPsSettledOffchain(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCNOPsSettledOffchain) (event.Subscription, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "NOPsSettledOffchain") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCNOPsSettledOffchain) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "NOPsSettledOffchain", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseNOPsSettledOffchain(log types.Log) (*AutomationRegistryLogicCNOPsSettledOffchain, error) { + event := new(AutomationRegistryLogicCNOPsSettledOffchain) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "NOPsSettledOffchain", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCOwnershipTransferRequestedIterator struct { + Event *AutomationRegistryLogicCOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AutomationRegistryLogicCOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCOwnershipTransferRequestedIterator{contract: _AutomationRegistryLogicC.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCOwnershipTransferRequested) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseOwnershipTransferRequested(log types.Log) (*AutomationRegistryLogicCOwnershipTransferRequested, error) { + event := new(AutomationRegistryLogicCOwnershipTransferRequested) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCOwnershipTransferredIterator struct { + Event *AutomationRegistryLogicCOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AutomationRegistryLogicCOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCOwnershipTransferredIterator{contract: _AutomationRegistryLogicC.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCOwnershipTransferred) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseOwnershipTransferred(log types.Log) (*AutomationRegistryLogicCOwnershipTransferred, error) { + event := new(AutomationRegistryLogicCOwnershipTransferred) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCPausedIterator struct { + Event *AutomationRegistryLogicCPaused + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCPausedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCPausedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCPausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCPaused struct { + Account common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterPaused(opts *bind.FilterOpts) (*AutomationRegistryLogicCPausedIterator, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "Paused") + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCPausedIterator{contract: _AutomationRegistryLogicC.contract, event: "Paused", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPaused) (event.Subscription, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "Paused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCPaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "Paused", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParsePaused(log types.Log) (*AutomationRegistryLogicCPaused, error) { + event := new(AutomationRegistryLogicCPaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "Paused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCPayeesUpdatedIterator struct { + Event *AutomationRegistryLogicCPayeesUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCPayeesUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPayeesUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPayeesUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCPayeesUpdatedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCPayeesUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCPayeesUpdated struct { + Transmitters []common.Address + Payees []common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterPayeesUpdated(opts *bind.FilterOpts) (*AutomationRegistryLogicCPayeesUpdatedIterator, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "PayeesUpdated") + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCPayeesUpdatedIterator{contract: _AutomationRegistryLogicC.contract, event: "PayeesUpdated", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchPayeesUpdated(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPayeesUpdated) (event.Subscription, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "PayeesUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCPayeesUpdated) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PayeesUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParsePayeesUpdated(log types.Log) (*AutomationRegistryLogicCPayeesUpdated, error) { + event := new(AutomationRegistryLogicCPayeesUpdated) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PayeesUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCPayeeshipTransferRequestedIterator struct { + Event *AutomationRegistryLogicCPayeeshipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCPayeeshipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPayeeshipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPayeeshipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCPayeeshipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCPayeeshipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCPayeeshipTransferRequested struct { + Transmitter common.Address + From common.Address + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterPayeeshipTransferRequested(opts *bind.FilterOpts, transmitter []common.Address, from []common.Address, to []common.Address) (*AutomationRegistryLogicCPayeeshipTransferRequestedIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "PayeeshipTransferRequested", transmitterRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCPayeeshipTransferRequestedIterator{contract: _AutomationRegistryLogicC.contract, event: "PayeeshipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchPayeeshipTransferRequested(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPayeeshipTransferRequested, transmitter []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "PayeeshipTransferRequested", transmitterRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCPayeeshipTransferRequested) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PayeeshipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParsePayeeshipTransferRequested(log types.Log) (*AutomationRegistryLogicCPayeeshipTransferRequested, error) { + event := new(AutomationRegistryLogicCPayeeshipTransferRequested) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PayeeshipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCPayeeshipTransferredIterator struct { + Event *AutomationRegistryLogicCPayeeshipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCPayeeshipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPayeeshipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPayeeshipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCPayeeshipTransferredIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCPayeeshipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCPayeeshipTransferred struct { + Transmitter common.Address + From common.Address + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterPayeeshipTransferred(opts *bind.FilterOpts, transmitter []common.Address, from []common.Address, to []common.Address) (*AutomationRegistryLogicCPayeeshipTransferredIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "PayeeshipTransferred", transmitterRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCPayeeshipTransferredIterator{contract: _AutomationRegistryLogicC.contract, event: "PayeeshipTransferred", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchPayeeshipTransferred(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPayeeshipTransferred, transmitter []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "PayeeshipTransferred", transmitterRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCPayeeshipTransferred) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PayeeshipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParsePayeeshipTransferred(log types.Log) (*AutomationRegistryLogicCPayeeshipTransferred, error) { + event := new(AutomationRegistryLogicCPayeeshipTransferred) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PayeeshipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCPaymentWithdrawnIterator struct { + Event *AutomationRegistryLogicCPaymentWithdrawn + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCPaymentWithdrawnIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPaymentWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCPaymentWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCPaymentWithdrawnIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCPaymentWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCPaymentWithdrawn struct { + Transmitter common.Address + Amount *big.Int + To common.Address + Payee common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterPaymentWithdrawn(opts *bind.FilterOpts, transmitter []common.Address, amount []*big.Int, to []common.Address) (*AutomationRegistryLogicCPaymentWithdrawnIterator, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var amountRule []interface{} + for _, amountItem := range amount { + amountRule = append(amountRule, amountItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "PaymentWithdrawn", transmitterRule, amountRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCPaymentWithdrawnIterator{contract: _AutomationRegistryLogicC.contract, event: "PaymentWithdrawn", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchPaymentWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPaymentWithdrawn, transmitter []common.Address, amount []*big.Int, to []common.Address) (event.Subscription, error) { + + var transmitterRule []interface{} + for _, transmitterItem := range transmitter { + transmitterRule = append(transmitterRule, transmitterItem) + } + var amountRule []interface{} + for _, amountItem := range amount { + amountRule = append(amountRule, amountItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "PaymentWithdrawn", transmitterRule, amountRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCPaymentWithdrawn) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PaymentWithdrawn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParsePaymentWithdrawn(log types.Log) (*AutomationRegistryLogicCPaymentWithdrawn, error) { + event := new(AutomationRegistryLogicCPaymentWithdrawn) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "PaymentWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCReorgedUpkeepReportIterator struct { + Event *AutomationRegistryLogicCReorgedUpkeepReport + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCReorgedUpkeepReportIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCReorgedUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCReorgedUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCReorgedUpkeepReportIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCReorgedUpkeepReportIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCReorgedUpkeepReport struct { + Id *big.Int + Trigger []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterReorgedUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCReorgedUpkeepReportIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "ReorgedUpkeepReport", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCReorgedUpkeepReportIterator{contract: _AutomationRegistryLogicC.contract, event: "ReorgedUpkeepReport", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchReorgedUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCReorgedUpkeepReport, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "ReorgedUpkeepReport", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCReorgedUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "ReorgedUpkeepReport", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseReorgedUpkeepReport(log types.Log) (*AutomationRegistryLogicCReorgedUpkeepReport, error) { + event := new(AutomationRegistryLogicCReorgedUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "ReorgedUpkeepReport", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCStaleUpkeepReportIterator struct { + Event *AutomationRegistryLogicCStaleUpkeepReport + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCStaleUpkeepReportIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCStaleUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCStaleUpkeepReport) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCStaleUpkeepReportIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCStaleUpkeepReportIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCStaleUpkeepReport struct { + Id *big.Int + Trigger []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterStaleUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCStaleUpkeepReportIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "StaleUpkeepReport", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCStaleUpkeepReportIterator{contract: _AutomationRegistryLogicC.contract, event: "StaleUpkeepReport", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchStaleUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCStaleUpkeepReport, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "StaleUpkeepReport", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCStaleUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "StaleUpkeepReport", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseStaleUpkeepReport(log types.Log) (*AutomationRegistryLogicCStaleUpkeepReport, error) { + event := new(AutomationRegistryLogicCStaleUpkeepReport) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "StaleUpkeepReport", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUnpausedIterator struct { + Event *AutomationRegistryLogicCUnpaused + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUnpausedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUnpausedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUnpausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUnpaused struct { + Account common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUnpaused(opts *bind.FilterOpts) (*AutomationRegistryLogicCUnpausedIterator, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUnpausedIterator{contract: _AutomationRegistryLogicC.contract, event: "Unpaused", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUnpaused) (event.Subscription, error) { + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUnpaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "Unpaused", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUnpaused(log types.Log) (*AutomationRegistryLogicCUnpaused, error) { + event := new(AutomationRegistryLogicCUnpaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "Unpaused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator struct { + Event *AutomationRegistryLogicCUpkeepAdminTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepAdminTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepAdminTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepAdminTransferRequested struct { + Id *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepAdminTransferRequested(opts *bind.FilterOpts, id []*big.Int, from []common.Address, to []common.Address) (*AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepAdminTransferRequested", idRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepAdminTransferRequested", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepAdminTransferRequested(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepAdminTransferRequested, id []*big.Int, from []common.Address, to []common.Address) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepAdminTransferRequested", idRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepAdminTransferRequested) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepAdminTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepAdminTransferRequested(log types.Log) (*AutomationRegistryLogicCUpkeepAdminTransferRequested, error) { + event := new(AutomationRegistryLogicCUpkeepAdminTransferRequested) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepAdminTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepAdminTransferredIterator struct { + Event *AutomationRegistryLogicCUpkeepAdminTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepAdminTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepAdminTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepAdminTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepAdminTransferredIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepAdminTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepAdminTransferred struct { + Id *big.Int + From common.Address + To common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepAdminTransferred(opts *bind.FilterOpts, id []*big.Int, from []common.Address, to []common.Address) (*AutomationRegistryLogicCUpkeepAdminTransferredIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepAdminTransferred", idRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepAdminTransferredIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepAdminTransferred", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepAdminTransferred(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepAdminTransferred, id []*big.Int, from []common.Address, to []common.Address) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepAdminTransferred", idRule, fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepAdminTransferred) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepAdminTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepAdminTransferred(log types.Log) (*AutomationRegistryLogicCUpkeepAdminTransferred, error) { + event := new(AutomationRegistryLogicCUpkeepAdminTransferred) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepAdminTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepCanceledIterator struct { + Event *AutomationRegistryLogicCUpkeepCanceled + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepCanceledIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepCanceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepCanceled) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepCanceledIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepCanceledIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepCanceled struct { + Id *big.Int + AtBlockHeight uint64 + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepCanceled(opts *bind.FilterOpts, id []*big.Int, atBlockHeight []uint64) (*AutomationRegistryLogicCUpkeepCanceledIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var atBlockHeightRule []interface{} + for _, atBlockHeightItem := range atBlockHeight { + atBlockHeightRule = append(atBlockHeightRule, atBlockHeightItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepCanceled", idRule, atBlockHeightRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepCanceledIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepCanceled", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepCanceled(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepCanceled, id []*big.Int, atBlockHeight []uint64) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var atBlockHeightRule []interface{} + for _, atBlockHeightItem := range atBlockHeight { + atBlockHeightRule = append(atBlockHeightRule, atBlockHeightItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepCanceled", idRule, atBlockHeightRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepCanceled) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepCanceled", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepCanceled(log types.Log) (*AutomationRegistryLogicCUpkeepCanceled, error) { + event := new(AutomationRegistryLogicCUpkeepCanceled) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepCanceled", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepChargedIterator struct { + Event *AutomationRegistryLogicCUpkeepCharged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepChargedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepCharged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepCharged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepChargedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepChargedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepCharged struct { + Id *big.Int + Receipt AutomationRegistryBase23PaymentReceipt + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepCharged(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepChargedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepCharged", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepChargedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepCharged", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepCharged(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepCharged, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepCharged", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepCharged) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepCharged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepCharged(log types.Log) (*AutomationRegistryLogicCUpkeepCharged, error) { + event := new(AutomationRegistryLogicCUpkeepCharged) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepCharged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepCheckDataSetIterator struct { + Event *AutomationRegistryLogicCUpkeepCheckDataSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepCheckDataSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepCheckDataSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepCheckDataSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepCheckDataSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepCheckDataSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepCheckDataSet struct { + Id *big.Int + NewCheckData []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepCheckDataSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepCheckDataSetIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepCheckDataSet", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepCheckDataSetIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepCheckDataSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepCheckDataSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepCheckDataSet, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepCheckDataSet", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepCheckDataSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepCheckDataSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepCheckDataSet(log types.Log) (*AutomationRegistryLogicCUpkeepCheckDataSet, error) { + event := new(AutomationRegistryLogicCUpkeepCheckDataSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepCheckDataSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepGasLimitSetIterator struct { + Event *AutomationRegistryLogicCUpkeepGasLimitSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepGasLimitSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepGasLimitSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepGasLimitSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepGasLimitSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepGasLimitSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepGasLimitSet struct { + Id *big.Int + GasLimit *big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepGasLimitSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepGasLimitSetIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepGasLimitSet", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepGasLimitSetIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepGasLimitSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepGasLimitSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepGasLimitSet, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepGasLimitSet", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepGasLimitSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepGasLimitSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepGasLimitSet(log types.Log) (*AutomationRegistryLogicCUpkeepGasLimitSet, error) { + event := new(AutomationRegistryLogicCUpkeepGasLimitSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepGasLimitSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepMigratedIterator struct { + Event *AutomationRegistryLogicCUpkeepMigrated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepMigratedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepMigrated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepMigrated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepMigratedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepMigratedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepMigrated struct { + Id *big.Int + RemainingBalance *big.Int + Destination common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepMigrated(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepMigratedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepMigrated", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepMigratedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepMigrated", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepMigrated(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepMigrated, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepMigrated", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepMigrated) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepMigrated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepMigrated(log types.Log) (*AutomationRegistryLogicCUpkeepMigrated, error) { + event := new(AutomationRegistryLogicCUpkeepMigrated) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepMigrated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepOffchainConfigSetIterator struct { + Event *AutomationRegistryLogicCUpkeepOffchainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepOffchainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepOffchainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepOffchainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepOffchainConfigSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepOffchainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepOffchainConfigSet struct { + Id *big.Int + OffchainConfig []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepOffchainConfigSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepOffchainConfigSetIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepOffchainConfigSet", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepOffchainConfigSetIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepOffchainConfigSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepOffchainConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepOffchainConfigSet, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepOffchainConfigSet", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepOffchainConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepOffchainConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepOffchainConfigSet(log types.Log) (*AutomationRegistryLogicCUpkeepOffchainConfigSet, error) { + event := new(AutomationRegistryLogicCUpkeepOffchainConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepOffchainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepPausedIterator struct { + Event *AutomationRegistryLogicCUpkeepPaused + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepPausedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepPausedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepPausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepPaused struct { + Id *big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepPaused(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepPausedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepPaused", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepPausedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepPaused", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepPaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepPaused, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepPaused", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepPaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepPaused", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepPaused(log types.Log) (*AutomationRegistryLogicCUpkeepPaused, error) { + event := new(AutomationRegistryLogicCUpkeepPaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepPaused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepPerformedIterator struct { + Event *AutomationRegistryLogicCUpkeepPerformed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepPerformedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepPerformed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepPerformed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepPerformedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepPerformedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepPerformed struct { + Id *big.Int + Success bool + TotalPayment *big.Int + GasUsed *big.Int + GasOverhead *big.Int + Trigger []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepPerformed(opts *bind.FilterOpts, id []*big.Int, success []bool) (*AutomationRegistryLogicCUpkeepPerformedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var successRule []interface{} + for _, successItem := range success { + successRule = append(successRule, successItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepPerformed", idRule, successRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepPerformedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepPerformed", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepPerformed(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepPerformed, id []*big.Int, success []bool) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + var successRule []interface{} + for _, successItem := range success { + successRule = append(successRule, successItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepPerformed", idRule, successRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepPerformed) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepPerformed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepPerformed(log types.Log) (*AutomationRegistryLogicCUpkeepPerformed, error) { + event := new(AutomationRegistryLogicCUpkeepPerformed) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepPerformed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator struct { + Event *AutomationRegistryLogicCUpkeepPrivilegeConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepPrivilegeConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepPrivilegeConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepPrivilegeConfigSet struct { + Id *big.Int + PrivilegeConfig []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepPrivilegeConfigSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepPrivilegeConfigSet", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepPrivilegeConfigSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepPrivilegeConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepPrivilegeConfigSet, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepPrivilegeConfigSet", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepPrivilegeConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepPrivilegeConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepPrivilegeConfigSet(log types.Log) (*AutomationRegistryLogicCUpkeepPrivilegeConfigSet, error) { + event := new(AutomationRegistryLogicCUpkeepPrivilegeConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepPrivilegeConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepReceivedIterator struct { + Event *AutomationRegistryLogicCUpkeepReceived + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepReceivedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepReceived) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepReceived) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepReceivedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepReceivedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepReceived struct { + Id *big.Int + StartingBalance *big.Int + ImportedFrom common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepReceived(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepReceivedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepReceived", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepReceivedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepReceived", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepReceived(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepReceived, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepReceived", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepReceived) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepReceived", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepReceived(log types.Log) (*AutomationRegistryLogicCUpkeepReceived, error) { + event := new(AutomationRegistryLogicCUpkeepReceived) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepReceived", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepRegisteredIterator struct { + Event *AutomationRegistryLogicCUpkeepRegistered + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepRegisteredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepRegistered) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepRegisteredIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepRegistered struct { + Id *big.Int + PerformGas uint32 + Admin common.Address + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepRegistered(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepRegisteredIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepRegistered", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepRegisteredIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepRegistered", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepRegistered(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepRegistered, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepRegistered", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepRegistered) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepRegistered", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepRegistered(log types.Log) (*AutomationRegistryLogicCUpkeepRegistered, error) { + event := new(AutomationRegistryLogicCUpkeepRegistered) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepTriggerConfigSetIterator struct { + Event *AutomationRegistryLogicCUpkeepTriggerConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepTriggerConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepTriggerConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepTriggerConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepTriggerConfigSetIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepTriggerConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepTriggerConfigSet struct { + Id *big.Int + TriggerConfig []byte + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepTriggerConfigSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepTriggerConfigSetIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepTriggerConfigSet", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepTriggerConfigSetIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepTriggerConfigSet", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepTriggerConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepTriggerConfigSet, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepTriggerConfigSet", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepTriggerConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepTriggerConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepTriggerConfigSet(log types.Log) (*AutomationRegistryLogicCUpkeepTriggerConfigSet, error) { + event := new(AutomationRegistryLogicCUpkeepTriggerConfigSet) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepTriggerConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AutomationRegistryLogicCUpkeepUnpausedIterator struct { + Event *AutomationRegistryLogicCUpkeepUnpaused + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AutomationRegistryLogicCUpkeepUnpausedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AutomationRegistryLogicCUpkeepUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AutomationRegistryLogicCUpkeepUnpausedIterator) Error() error { + return it.fail +} + +func (it *AutomationRegistryLogicCUpkeepUnpausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AutomationRegistryLogicCUpkeepUnpaused struct { + Id *big.Int + Raw types.Log +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) FilterUpkeepUnpaused(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepUnpausedIterator, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.FilterLogs(opts, "UpkeepUnpaused", idRule) + if err != nil { + return nil, err + } + return &AutomationRegistryLogicCUpkeepUnpausedIterator{contract: _AutomationRegistryLogicC.contract, event: "UpkeepUnpaused", logs: logs, sub: sub}, nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) WatchUpkeepUnpaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepUnpaused, id []*big.Int) (event.Subscription, error) { + + var idRule []interface{} + for _, idItem := range id { + idRule = append(idRule, idItem) + } + + logs, sub, err := _AutomationRegistryLogicC.contract.WatchLogs(opts, "UpkeepUnpaused", idRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AutomationRegistryLogicCUpkeepUnpaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepUnpaused", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicCFilterer) ParseUpkeepUnpaused(log types.Log) (*AutomationRegistryLogicCUpkeepUnpaused, error) { + event := new(AutomationRegistryLogicCUpkeepUnpaused) + if err := _AutomationRegistryLogicC.contract.UnpackLog(event, "UpkeepUnpaused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetSignerInfo struct { + Active bool + Index uint8 +} +type GetState struct { + State IAutomationV21PlusCommonStateLegacy + Config IAutomationV21PlusCommonOnchainConfigLegacy + Signers []common.Address + Transmitters []common.Address + F uint8 +} +type GetTransmitterInfo struct { + Active bool + Index uint8 + Balance *big.Int + LastCollected *big.Int + Payee common.Address +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicC) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _AutomationRegistryLogicC.abi.Events["AdminPrivilegeConfigSet"].ID: + return _AutomationRegistryLogicC.ParseAdminPrivilegeConfigSet(log) + case _AutomationRegistryLogicC.abi.Events["BillingConfigOverridden"].ID: + return _AutomationRegistryLogicC.ParseBillingConfigOverridden(log) + case _AutomationRegistryLogicC.abi.Events["BillingConfigOverrideRemoved"].ID: + return _AutomationRegistryLogicC.ParseBillingConfigOverrideRemoved(log) + case _AutomationRegistryLogicC.abi.Events["BillingConfigSet"].ID: + return _AutomationRegistryLogicC.ParseBillingConfigSet(log) + case _AutomationRegistryLogicC.abi.Events["CancelledUpkeepReport"].ID: + return _AutomationRegistryLogicC.ParseCancelledUpkeepReport(log) + case _AutomationRegistryLogicC.abi.Events["ChainSpecificModuleUpdated"].ID: + return _AutomationRegistryLogicC.ParseChainSpecificModuleUpdated(log) + case _AutomationRegistryLogicC.abi.Events["DedupKeyAdded"].ID: + return _AutomationRegistryLogicC.ParseDedupKeyAdded(log) + case _AutomationRegistryLogicC.abi.Events["FeesWithdrawn"].ID: + return _AutomationRegistryLogicC.ParseFeesWithdrawn(log) + case _AutomationRegistryLogicC.abi.Events["FundsAdded"].ID: + return _AutomationRegistryLogicC.ParseFundsAdded(log) + case _AutomationRegistryLogicC.abi.Events["FundsWithdrawn"].ID: + return _AutomationRegistryLogicC.ParseFundsWithdrawn(log) + case _AutomationRegistryLogicC.abi.Events["InsufficientFundsUpkeepReport"].ID: + return _AutomationRegistryLogicC.ParseInsufficientFundsUpkeepReport(log) + case _AutomationRegistryLogicC.abi.Events["NOPsSettledOffchain"].ID: + return _AutomationRegistryLogicC.ParseNOPsSettledOffchain(log) + case _AutomationRegistryLogicC.abi.Events["OwnershipTransferRequested"].ID: + return _AutomationRegistryLogicC.ParseOwnershipTransferRequested(log) + case _AutomationRegistryLogicC.abi.Events["OwnershipTransferred"].ID: + return _AutomationRegistryLogicC.ParseOwnershipTransferred(log) + case _AutomationRegistryLogicC.abi.Events["Paused"].ID: + return _AutomationRegistryLogicC.ParsePaused(log) + case _AutomationRegistryLogicC.abi.Events["PayeesUpdated"].ID: + return _AutomationRegistryLogicC.ParsePayeesUpdated(log) + case _AutomationRegistryLogicC.abi.Events["PayeeshipTransferRequested"].ID: + return _AutomationRegistryLogicC.ParsePayeeshipTransferRequested(log) + case _AutomationRegistryLogicC.abi.Events["PayeeshipTransferred"].ID: + return _AutomationRegistryLogicC.ParsePayeeshipTransferred(log) + case _AutomationRegistryLogicC.abi.Events["PaymentWithdrawn"].ID: + return _AutomationRegistryLogicC.ParsePaymentWithdrawn(log) + case _AutomationRegistryLogicC.abi.Events["ReorgedUpkeepReport"].ID: + return _AutomationRegistryLogicC.ParseReorgedUpkeepReport(log) + case _AutomationRegistryLogicC.abi.Events["StaleUpkeepReport"].ID: + return _AutomationRegistryLogicC.ParseStaleUpkeepReport(log) + case _AutomationRegistryLogicC.abi.Events["Unpaused"].ID: + return _AutomationRegistryLogicC.ParseUnpaused(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepAdminTransferRequested"].ID: + return _AutomationRegistryLogicC.ParseUpkeepAdminTransferRequested(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepAdminTransferred"].ID: + return _AutomationRegistryLogicC.ParseUpkeepAdminTransferred(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepCanceled"].ID: + return _AutomationRegistryLogicC.ParseUpkeepCanceled(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepCharged"].ID: + return _AutomationRegistryLogicC.ParseUpkeepCharged(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepCheckDataSet"].ID: + return _AutomationRegistryLogicC.ParseUpkeepCheckDataSet(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepGasLimitSet"].ID: + return _AutomationRegistryLogicC.ParseUpkeepGasLimitSet(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepMigrated"].ID: + return _AutomationRegistryLogicC.ParseUpkeepMigrated(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepOffchainConfigSet"].ID: + return _AutomationRegistryLogicC.ParseUpkeepOffchainConfigSet(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepPaused"].ID: + return _AutomationRegistryLogicC.ParseUpkeepPaused(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepPerformed"].ID: + return _AutomationRegistryLogicC.ParseUpkeepPerformed(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepPrivilegeConfigSet"].ID: + return _AutomationRegistryLogicC.ParseUpkeepPrivilegeConfigSet(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepReceived"].ID: + return _AutomationRegistryLogicC.ParseUpkeepReceived(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepRegistered"].ID: + return _AutomationRegistryLogicC.ParseUpkeepRegistered(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepTriggerConfigSet"].ID: + return _AutomationRegistryLogicC.ParseUpkeepTriggerConfigSet(log) + case _AutomationRegistryLogicC.abi.Events["UpkeepUnpaused"].ID: + return _AutomationRegistryLogicC.ParseUpkeepUnpaused(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (AutomationRegistryLogicCAdminPrivilegeConfigSet) Topic() common.Hash { + return common.HexToHash("0x7c44b4eb59ee7873514e7e43e7718c269d872965938b288aa143befca62f99d2") +} + +func (AutomationRegistryLogicCBillingConfigOverridden) Topic() common.Hash { + return common.HexToHash("0xd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340") +} + +func (AutomationRegistryLogicCBillingConfigOverrideRemoved) Topic() common.Hash { + return common.HexToHash("0x97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a") +} + +func (AutomationRegistryLogicCBillingConfigSet) Topic() common.Hash { + return common.HexToHash("0xca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba3") +} + +func (AutomationRegistryLogicCCancelledUpkeepReport) Topic() common.Hash { + return common.HexToHash("0xc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636") +} + +func (AutomationRegistryLogicCChainSpecificModuleUpdated) Topic() common.Hash { + return common.HexToHash("0xdefc28b11a7980dbe0c49dbbd7055a1584bc8075097d1e8b3b57fb7283df2ad7") +} + +func (AutomationRegistryLogicCDedupKeyAdded) Topic() common.Hash { + return common.HexToHash("0xa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f2") +} + +func (AutomationRegistryLogicCFeesWithdrawn) Topic() common.Hash { + return common.HexToHash("0x5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa8") +} + +func (AutomationRegistryLogicCFundsAdded) Topic() common.Hash { + return common.HexToHash("0xafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203") +} + +func (AutomationRegistryLogicCFundsWithdrawn) Topic() common.Hash { + return common.HexToHash("0xf3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318") +} + +func (AutomationRegistryLogicCInsufficientFundsUpkeepReport) Topic() common.Hash { + return common.HexToHash("0x377c8b0c126ae5248d27aca1c76fac4608aff85673ee3caf09747e1044549e02") +} + +func (AutomationRegistryLogicCNOPsSettledOffchain) Topic() common.Hash { + return common.HexToHash("0x5af23b715253628d12b660b27a4f3fc626562ea8a55040aa99ab3dc178989fad") +} + +func (AutomationRegistryLogicCOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (AutomationRegistryLogicCOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (AutomationRegistryLogicCPaused) Topic() common.Hash { + return common.HexToHash("0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258") +} + +func (AutomationRegistryLogicCPayeesUpdated) Topic() common.Hash { + return common.HexToHash("0xa46de38886467c59be07a0675f14781206a5477d871628af46c2443822fcb725") +} + +func (AutomationRegistryLogicCPayeeshipTransferRequested) Topic() common.Hash { + return common.HexToHash("0x84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e38367") +} + +func (AutomationRegistryLogicCPayeeshipTransferred) Topic() common.Hash { + return common.HexToHash("0x78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b3") +} + +func (AutomationRegistryLogicCPaymentWithdrawn) Topic() common.Hash { + return common.HexToHash("0x9819093176a1851202c7bcfa46845809b4e47c261866550e94ed3775d2f40698") +} + +func (AutomationRegistryLogicCReorgedUpkeepReport) Topic() common.Hash { + return common.HexToHash("0x6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301") +} + +func (AutomationRegistryLogicCStaleUpkeepReport) Topic() common.Hash { + return common.HexToHash("0x405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8") +} + +func (AutomationRegistryLogicCUnpaused) Topic() common.Hash { + return common.HexToHash("0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa") +} + +func (AutomationRegistryLogicCUpkeepAdminTransferRequested) Topic() common.Hash { + return common.HexToHash("0xb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b35") +} + +func (AutomationRegistryLogicCUpkeepAdminTransferred) Topic() common.Hash { + return common.HexToHash("0x5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c") +} + +func (AutomationRegistryLogicCUpkeepCanceled) Topic() common.Hash { + return common.HexToHash("0x91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f791181") +} + +func (AutomationRegistryLogicCUpkeepCharged) Topic() common.Hash { + return common.HexToHash("0x801ba6ed51146ffe3e99d1dbd9dd0f4de6292e78a9a34c39c0183de17b3f40fc") +} + +func (AutomationRegistryLogicCUpkeepCheckDataSet) Topic() common.Hash { + return common.HexToHash("0xcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d") +} + +func (AutomationRegistryLogicCUpkeepGasLimitSet) Topic() common.Hash { + return common.HexToHash("0xc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c") +} + +func (AutomationRegistryLogicCUpkeepMigrated) Topic() common.Hash { + return common.HexToHash("0xb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff") +} + +func (AutomationRegistryLogicCUpkeepOffchainConfigSet) Topic() common.Hash { + return common.HexToHash("0x3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850") +} + +func (AutomationRegistryLogicCUpkeepPaused) Topic() common.Hash { + return common.HexToHash("0x8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f") +} + +func (AutomationRegistryLogicCUpkeepPerformed) Topic() common.Hash { + return common.HexToHash("0xad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b") +} + +func (AutomationRegistryLogicCUpkeepPrivilegeConfigSet) Topic() common.Hash { + return common.HexToHash("0x2fd8d70753a007014349d4591843cc031c2dd7a260d7dd82eca8253686ae7769") +} + +func (AutomationRegistryLogicCUpkeepReceived) Topic() common.Hash { + return common.HexToHash("0x74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a71") +} + +func (AutomationRegistryLogicCUpkeepRegistered) Topic() common.Hash { + return common.HexToHash("0xbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d012") +} + +func (AutomationRegistryLogicCUpkeepTriggerConfigSet) Topic() common.Hash { + return common.HexToHash("0x2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664") +} + +func (AutomationRegistryLogicCUpkeepUnpaused) Topic() common.Hash { + return common.HexToHash("0x7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a47456") +} + +func (_AutomationRegistryLogicC *AutomationRegistryLogicC) Address() common.Address { + return _AutomationRegistryLogicC.address +} + +type AutomationRegistryLogicCInterface interface { + GetActiveUpkeepIDs(opts *bind.CallOpts, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) + + GetAdminPrivilegeConfig(opts *bind.CallOpts, admin common.Address) ([]byte, error) + + GetAllowedReadOnlyAddress(opts *bind.CallOpts) (common.Address, error) + + GetAutomationForwarderLogic(opts *bind.CallOpts) (common.Address, error) + + GetAvailableERC20ForPayment(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) + + GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) + + GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) + + GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) + + GetBillingOverridesEnabled(opts *bind.CallOpts, upkeepID *big.Int) (bool, error) + + GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) + + GetBillingTokenConfig(opts *bind.CallOpts, token common.Address) (AutomationRegistryBase23BillingConfig, error) + + GetBillingTokens(opts *bind.CallOpts) ([]common.Address, error) + + GetCancellationDelay(opts *bind.CallOpts) (*big.Int, error) + + GetChainModule(opts *bind.CallOpts) (common.Address, error) + + GetConditionalGasOverhead(opts *bind.CallOpts) (*big.Int, error) + + GetConfig(opts *bind.CallOpts) (AutomationRegistryBase23OnchainConfig, error) + + GetFallbackNativePrice(opts *bind.CallOpts) (*big.Int, error) + + GetFastGasFeedAddress(opts *bind.CallOpts) (common.Address, error) + + GetForwarder(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) + + GetHotVars(opts *bind.CallOpts) (AutomationRegistryBase23HotVars, error) + + GetLinkAddress(opts *bind.CallOpts) (common.Address, error) + + GetLinkUSDFeedAddress(opts *bind.CallOpts) (common.Address, error) + + GetLogGasOverhead(opts *bind.CallOpts) (*big.Int, error) + + GetMaxPaymentForGas(opts *bind.CallOpts, id *big.Int, triggerType uint8, gasLimit uint32, billingToken common.Address) (*big.Int, error) + + GetMinBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) + + GetMinBalanceForUpkeep(opts *bind.CallOpts, id *big.Int) (*big.Int, error) + + GetNativeUSDFeedAddress(opts *bind.CallOpts) (common.Address, error) + + GetNumUpkeeps(opts *bind.CallOpts) (*big.Int, error) + + GetPayoutMode(opts *bind.CallOpts) (uint8, error) + + GetPeerRegistryMigrationPermission(opts *bind.CallOpts, peer common.Address) (uint8, error) + + GetPerPerformByteGasOverhead(opts *bind.CallOpts) (*big.Int, error) + + GetPerSignerGasOverhead(opts *bind.CallOpts) (*big.Int, error) + + GetReorgProtectionEnabled(opts *bind.CallOpts) (bool, error) + + GetReserveAmount(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) + + GetSignerInfo(opts *bind.CallOpts, query common.Address) (GetSignerInfo, + + error) + + GetState(opts *bind.CallOpts) (GetState, + + error) + + GetStorage(opts *bind.CallOpts) (AutomationRegistryBase23Storage, error) + + GetTransmitCalldataFixedBytesOverhead(opts *bind.CallOpts) (*big.Int, error) + + GetTransmitCalldataPerSignerBytesOverhead(opts *bind.CallOpts) (*big.Int, error) + + GetTransmitterInfo(opts *bind.CallOpts, query common.Address) (GetTransmitterInfo, + + error) + + GetTransmittersWithPayees(opts *bind.CallOpts) ([]AutomationRegistryBase23TransmitterPayeeInfo, error) + + GetTriggerType(opts *bind.CallOpts, upkeepId *big.Int) (uint8, error) + + GetUpkeep(opts *bind.CallOpts, id *big.Int) (IAutomationV21PlusCommonUpkeepInfoLegacy, error) + + GetUpkeepPrivilegeConfig(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) + + GetUpkeepTriggerConfig(opts *bind.CallOpts, upkeepId *big.Int) ([]byte, error) + + GetWrappedNativeTokenAddress(opts *bind.CallOpts) (common.Address, error) + + HasDedupKey(opts *bind.CallOpts, dedupKey [32]byte) (bool, error) + + LinkAvailableForPayment(opts *bind.CallOpts) (*big.Int, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SupportsBillingToken(opts *bind.CallOpts, token common.Address) (bool, error) + + UpkeepVersion(opts *bind.CallOpts) (uint8, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AcceptPayeeship(opts *bind.TransactOpts, transmitter common.Address) (*types.Transaction, error) + + DisableOffchainPayments(opts *bind.TransactOpts) (*types.Transaction, error) + + Pause(opts *bind.TransactOpts) (*types.Transaction, error) + + SetAdminPrivilegeConfig(opts *bind.TransactOpts, admin common.Address, newPrivilegeConfig []byte) (*types.Transaction, error) + + SetPayees(opts *bind.TransactOpts, payees []common.Address) (*types.Transaction, error) + + SetPeerRegistryMigrationPermission(opts *bind.TransactOpts, peer common.Address, permission uint8) (*types.Transaction, error) + + SetUpkeepPrivilegeConfig(opts *bind.TransactOpts, upkeepId *big.Int, newPrivilegeConfig []byte) (*types.Transaction, error) + + SettleNOPsOffchain(opts *bind.TransactOpts) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + TransferPayeeship(opts *bind.TransactOpts, transmitter common.Address, proposed common.Address) (*types.Transaction, error) + + Unpause(opts *bind.TransactOpts) (*types.Transaction, error) + + WithdrawPayment(opts *bind.TransactOpts, from common.Address, to common.Address) (*types.Transaction, error) + + FilterAdminPrivilegeConfigSet(opts *bind.FilterOpts, admin []common.Address) (*AutomationRegistryLogicCAdminPrivilegeConfigSetIterator, error) + + WatchAdminPrivilegeConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCAdminPrivilegeConfigSet, admin []common.Address) (event.Subscription, error) + + ParseAdminPrivilegeConfigSet(log types.Log) (*AutomationRegistryLogicCAdminPrivilegeConfigSet, error) + + FilterBillingConfigOverridden(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCBillingConfigOverriddenIterator, error) + + WatchBillingConfigOverridden(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCBillingConfigOverridden, id []*big.Int) (event.Subscription, error) + + ParseBillingConfigOverridden(log types.Log) (*AutomationRegistryLogicCBillingConfigOverridden, error) + + FilterBillingConfigOverrideRemoved(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCBillingConfigOverrideRemovedIterator, error) + + WatchBillingConfigOverrideRemoved(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCBillingConfigOverrideRemoved, id []*big.Int) (event.Subscription, error) + + ParseBillingConfigOverrideRemoved(log types.Log) (*AutomationRegistryLogicCBillingConfigOverrideRemoved, error) + + FilterBillingConfigSet(opts *bind.FilterOpts, token []common.Address) (*AutomationRegistryLogicCBillingConfigSetIterator, error) + + WatchBillingConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCBillingConfigSet, token []common.Address) (event.Subscription, error) + + ParseBillingConfigSet(log types.Log) (*AutomationRegistryLogicCBillingConfigSet, error) + + FilterCancelledUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCCancelledUpkeepReportIterator, error) + + WatchCancelledUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCCancelledUpkeepReport, id []*big.Int) (event.Subscription, error) + + ParseCancelledUpkeepReport(log types.Log) (*AutomationRegistryLogicCCancelledUpkeepReport, error) + + FilterChainSpecificModuleUpdated(opts *bind.FilterOpts) (*AutomationRegistryLogicCChainSpecificModuleUpdatedIterator, error) + + WatchChainSpecificModuleUpdated(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCChainSpecificModuleUpdated) (event.Subscription, error) + + ParseChainSpecificModuleUpdated(log types.Log) (*AutomationRegistryLogicCChainSpecificModuleUpdated, error) + + FilterDedupKeyAdded(opts *bind.FilterOpts, dedupKey [][32]byte) (*AutomationRegistryLogicCDedupKeyAddedIterator, error) + + WatchDedupKeyAdded(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCDedupKeyAdded, dedupKey [][32]byte) (event.Subscription, error) + + ParseDedupKeyAdded(log types.Log) (*AutomationRegistryLogicCDedupKeyAdded, error) + + FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryLogicCFeesWithdrawnIterator, error) + + WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) + + ParseFeesWithdrawn(log types.Log) (*AutomationRegistryLogicCFeesWithdrawn, error) + + FilterFundsAdded(opts *bind.FilterOpts, id []*big.Int, from []common.Address) (*AutomationRegistryLogicCFundsAddedIterator, error) + + WatchFundsAdded(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCFundsAdded, id []*big.Int, from []common.Address) (event.Subscription, error) + + ParseFundsAdded(log types.Log) (*AutomationRegistryLogicCFundsAdded, error) + + FilterFundsWithdrawn(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCFundsWithdrawnIterator, error) + + WatchFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCFundsWithdrawn, id []*big.Int) (event.Subscription, error) + + ParseFundsWithdrawn(log types.Log) (*AutomationRegistryLogicCFundsWithdrawn, error) + + FilterInsufficientFundsUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCInsufficientFundsUpkeepReportIterator, error) + + WatchInsufficientFundsUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCInsufficientFundsUpkeepReport, id []*big.Int) (event.Subscription, error) + + ParseInsufficientFundsUpkeepReport(log types.Log) (*AutomationRegistryLogicCInsufficientFundsUpkeepReport, error) + + FilterNOPsSettledOffchain(opts *bind.FilterOpts) (*AutomationRegistryLogicCNOPsSettledOffchainIterator, error) + + WatchNOPsSettledOffchain(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCNOPsSettledOffchain) (event.Subscription, error) + + ParseNOPsSettledOffchain(log types.Log) (*AutomationRegistryLogicCNOPsSettledOffchain, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AutomationRegistryLogicCOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*AutomationRegistryLogicCOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AutomationRegistryLogicCOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*AutomationRegistryLogicCOwnershipTransferred, error) + + FilterPaused(opts *bind.FilterOpts) (*AutomationRegistryLogicCPausedIterator, error) + + WatchPaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPaused) (event.Subscription, error) + + ParsePaused(log types.Log) (*AutomationRegistryLogicCPaused, error) + + FilterPayeesUpdated(opts *bind.FilterOpts) (*AutomationRegistryLogicCPayeesUpdatedIterator, error) + + WatchPayeesUpdated(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPayeesUpdated) (event.Subscription, error) + + ParsePayeesUpdated(log types.Log) (*AutomationRegistryLogicCPayeesUpdated, error) + + FilterPayeeshipTransferRequested(opts *bind.FilterOpts, transmitter []common.Address, from []common.Address, to []common.Address) (*AutomationRegistryLogicCPayeeshipTransferRequestedIterator, error) + + WatchPayeeshipTransferRequested(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPayeeshipTransferRequested, transmitter []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) + + ParsePayeeshipTransferRequested(log types.Log) (*AutomationRegistryLogicCPayeeshipTransferRequested, error) + + FilterPayeeshipTransferred(opts *bind.FilterOpts, transmitter []common.Address, from []common.Address, to []common.Address) (*AutomationRegistryLogicCPayeeshipTransferredIterator, error) + + WatchPayeeshipTransferred(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPayeeshipTransferred, transmitter []common.Address, from []common.Address, to []common.Address) (event.Subscription, error) + + ParsePayeeshipTransferred(log types.Log) (*AutomationRegistryLogicCPayeeshipTransferred, error) + + FilterPaymentWithdrawn(opts *bind.FilterOpts, transmitter []common.Address, amount []*big.Int, to []common.Address) (*AutomationRegistryLogicCPaymentWithdrawnIterator, error) + + WatchPaymentWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCPaymentWithdrawn, transmitter []common.Address, amount []*big.Int, to []common.Address) (event.Subscription, error) + + ParsePaymentWithdrawn(log types.Log) (*AutomationRegistryLogicCPaymentWithdrawn, error) + + FilterReorgedUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCReorgedUpkeepReportIterator, error) + + WatchReorgedUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCReorgedUpkeepReport, id []*big.Int) (event.Subscription, error) + + ParseReorgedUpkeepReport(log types.Log) (*AutomationRegistryLogicCReorgedUpkeepReport, error) + + FilterStaleUpkeepReport(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCStaleUpkeepReportIterator, error) + + WatchStaleUpkeepReport(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCStaleUpkeepReport, id []*big.Int) (event.Subscription, error) + + ParseStaleUpkeepReport(log types.Log) (*AutomationRegistryLogicCStaleUpkeepReport, error) + + FilterUnpaused(opts *bind.FilterOpts) (*AutomationRegistryLogicCUnpausedIterator, error) + + WatchUnpaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUnpaused) (event.Subscription, error) + + ParseUnpaused(log types.Log) (*AutomationRegistryLogicCUnpaused, error) + + FilterUpkeepAdminTransferRequested(opts *bind.FilterOpts, id []*big.Int, from []common.Address, to []common.Address) (*AutomationRegistryLogicCUpkeepAdminTransferRequestedIterator, error) + + WatchUpkeepAdminTransferRequested(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepAdminTransferRequested, id []*big.Int, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseUpkeepAdminTransferRequested(log types.Log) (*AutomationRegistryLogicCUpkeepAdminTransferRequested, error) + + FilterUpkeepAdminTransferred(opts *bind.FilterOpts, id []*big.Int, from []common.Address, to []common.Address) (*AutomationRegistryLogicCUpkeepAdminTransferredIterator, error) + + WatchUpkeepAdminTransferred(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepAdminTransferred, id []*big.Int, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseUpkeepAdminTransferred(log types.Log) (*AutomationRegistryLogicCUpkeepAdminTransferred, error) + + FilterUpkeepCanceled(opts *bind.FilterOpts, id []*big.Int, atBlockHeight []uint64) (*AutomationRegistryLogicCUpkeepCanceledIterator, error) + + WatchUpkeepCanceled(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepCanceled, id []*big.Int, atBlockHeight []uint64) (event.Subscription, error) + + ParseUpkeepCanceled(log types.Log) (*AutomationRegistryLogicCUpkeepCanceled, error) + + FilterUpkeepCharged(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepChargedIterator, error) + + WatchUpkeepCharged(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepCharged, id []*big.Int) (event.Subscription, error) + + ParseUpkeepCharged(log types.Log) (*AutomationRegistryLogicCUpkeepCharged, error) + + FilterUpkeepCheckDataSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepCheckDataSetIterator, error) + + WatchUpkeepCheckDataSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepCheckDataSet, id []*big.Int) (event.Subscription, error) + + ParseUpkeepCheckDataSet(log types.Log) (*AutomationRegistryLogicCUpkeepCheckDataSet, error) + + FilterUpkeepGasLimitSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepGasLimitSetIterator, error) + + WatchUpkeepGasLimitSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepGasLimitSet, id []*big.Int) (event.Subscription, error) + + ParseUpkeepGasLimitSet(log types.Log) (*AutomationRegistryLogicCUpkeepGasLimitSet, error) + + FilterUpkeepMigrated(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepMigratedIterator, error) + + WatchUpkeepMigrated(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepMigrated, id []*big.Int) (event.Subscription, error) + + ParseUpkeepMigrated(log types.Log) (*AutomationRegistryLogicCUpkeepMigrated, error) + + FilterUpkeepOffchainConfigSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepOffchainConfigSetIterator, error) + + WatchUpkeepOffchainConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepOffchainConfigSet, id []*big.Int) (event.Subscription, error) + + ParseUpkeepOffchainConfigSet(log types.Log) (*AutomationRegistryLogicCUpkeepOffchainConfigSet, error) + + FilterUpkeepPaused(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepPausedIterator, error) + + WatchUpkeepPaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepPaused, id []*big.Int) (event.Subscription, error) + + ParseUpkeepPaused(log types.Log) (*AutomationRegistryLogicCUpkeepPaused, error) + + FilterUpkeepPerformed(opts *bind.FilterOpts, id []*big.Int, success []bool) (*AutomationRegistryLogicCUpkeepPerformedIterator, error) + + WatchUpkeepPerformed(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepPerformed, id []*big.Int, success []bool) (event.Subscription, error) + + ParseUpkeepPerformed(log types.Log) (*AutomationRegistryLogicCUpkeepPerformed, error) + + FilterUpkeepPrivilegeConfigSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepPrivilegeConfigSetIterator, error) + + WatchUpkeepPrivilegeConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepPrivilegeConfigSet, id []*big.Int) (event.Subscription, error) + + ParseUpkeepPrivilegeConfigSet(log types.Log) (*AutomationRegistryLogicCUpkeepPrivilegeConfigSet, error) + + FilterUpkeepReceived(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepReceivedIterator, error) + + WatchUpkeepReceived(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepReceived, id []*big.Int) (event.Subscription, error) + + ParseUpkeepReceived(log types.Log) (*AutomationRegistryLogicCUpkeepReceived, error) + + FilterUpkeepRegistered(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepRegisteredIterator, error) + + WatchUpkeepRegistered(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepRegistered, id []*big.Int) (event.Subscription, error) + + ParseUpkeepRegistered(log types.Log) (*AutomationRegistryLogicCUpkeepRegistered, error) + + FilterUpkeepTriggerConfigSet(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepTriggerConfigSetIterator, error) + + WatchUpkeepTriggerConfigSet(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepTriggerConfigSet, id []*big.Int) (event.Subscription, error) + + ParseUpkeepTriggerConfigSet(log types.Log) (*AutomationRegistryLogicCUpkeepTriggerConfigSet, error) + + FilterUpkeepUnpaused(opts *bind.FilterOpts, id []*big.Int) (*AutomationRegistryLogicCUpkeepUnpausedIterator, error) + + WatchUpkeepUnpaused(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicCUpkeepUnpaused, id []*big.Int) (event.Subscription, error) + + ParseUpkeepUnpaused(log types.Log) (*AutomationRegistryLogicCUpkeepUnpaused, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go index 471416f7f7..e41c6fa669 100644 --- a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go +++ b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go @@ -150,7 +150,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { } var IAutomationRegistryMaster23MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint96\",\"name\":\"gasChargeInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"gasReimbursementInJuels\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"linkUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"billingUSD\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.PaymentReceipt\",\"name\":\"receipt\",\"type\":\"tuple\"}],\"name\":\"UpkeepCharged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getAvailableERC20ForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint96\",\"name\":\"gasChargeInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInBillingToken\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"gasReimbursementInJuels\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"premiumInJuels\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"linkUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeUSD\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"billingUSD\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.PaymentReceipt\",\"name\":\"receipt\",\"type\":\"tuple\"}],\"name\":\"UpkeepCharged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getAvailableERC20ForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverridesEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var IAutomationRegistryMaster23ABI = IAutomationRegistryMaster23MetaData.ABI @@ -571,6 +571,28 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetBillingOverrides(&_IAutomationRegistryMaster23.CallOpts, upkeepID) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingOverridesEnabled(opts *bind.CallOpts, upkeepID *big.Int) (bool, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingOverridesEnabled", upkeepID) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetBillingOverridesEnabled(upkeepID *big.Int) (bool, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingOverridesEnabled(&_IAutomationRegistryMaster23.CallOpts, upkeepID) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetBillingOverridesEnabled(upkeepID *big.Int) (bool, error) { + return _IAutomationRegistryMaster23.Contract.GetBillingOverridesEnabled(&_IAutomationRegistryMaster23.CallOpts, upkeepID) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBillingToken", upkeepID) @@ -7483,6 +7505,8 @@ type IAutomationRegistryMaster23Interface interface { GetBillingOverrides(opts *bind.CallOpts, upkeepID *big.Int) (AutomationRegistryBase23BillingOverrides, error) + GetBillingOverridesEnabled(opts *bind.CallOpts, upkeepID *big.Int) (bool, error) + GetBillingToken(opts *bind.CallOpts, upkeepID *big.Int) (common.Address, error) GetBillingTokenConfig(opts *bind.CallOpts, token common.Address) (AutomationRegistryBase23BillingConfig, error) diff --git a/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper/mock_ethusd_aggregator_wrapper.go b/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper/mock_ethusd_aggregator_wrapper.go new file mode 100644 index 0000000000..c10f916c5e --- /dev/null +++ b/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper/mock_ethusd_aggregator_wrapper.go @@ -0,0 +1,377 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package mock_ethusd_aggregator_wrapper + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var MockETHUSDAggregatorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_answer\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"answer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"description\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"\",\"type\":\"uint80\"}],\"name\":\"getRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"ans\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"ans\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_blockTimestampDeduction\",\"type\":\"uint256\"}],\"name\":\"setBlockTimestampDeduction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x6080604052600060015534801561001557600080fd5b506040516103333803806103338339810160408190526100349161003c565b600055610055565b60006020828403121561004e57600080fd5b5051919050565b6102cf806100646000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806385bb7d691161005b57806385bb7d69146100e65780639a6fc8f5146100ef578063f0ad37df14610139578063feaf968c1461014e57600080fd5b8063313ce5671461008257806354fd4d50146100965780637284e416146100a7575b600080fd5b604051600881526020015b60405180910390f35b60015b60405190815260200161008d565b604080518082018252601481527f4d6f636b45544855534441676772656761746f720000000000000000000000006020820152905161008d91906101ca565b61009960005481565b6101026100fd366004610236565b610156565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a00161008d565b61014c610147366004610269565b600155565b005b610102610186565b6000806000806000600160005461016b6101b5565b6101736101b5565b9299919850965090945060019350915050565b6000806000806000600160005461019b6101b5565b6101a36101b5565b92989197509550909350600192509050565b6000600154426101c59190610282565b905090565b600060208083528351808285015260005b818110156101f7578581018301518582016040015282016101db565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561024857600080fd5b813569ffffffffffffffffffff8116811461026257600080fd5b9392505050565b60006020828403121561027b57600080fd5b5035919050565b818103818111156102bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000a", +} + +var MockETHUSDAggregatorABI = MockETHUSDAggregatorMetaData.ABI + +var MockETHUSDAggregatorBin = MockETHUSDAggregatorMetaData.Bin + +func DeployMockETHUSDAggregator(auth *bind.TransactOpts, backend bind.ContractBackend, _answer *big.Int) (common.Address, *types.Transaction, *MockETHUSDAggregator, error) { + parsed, err := MockETHUSDAggregatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MockETHUSDAggregatorBin), backend, _answer) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &MockETHUSDAggregator{address: address, abi: *parsed, MockETHUSDAggregatorCaller: MockETHUSDAggregatorCaller{contract: contract}, MockETHUSDAggregatorTransactor: MockETHUSDAggregatorTransactor{contract: contract}, MockETHUSDAggregatorFilterer: MockETHUSDAggregatorFilterer{contract: contract}}, nil +} + +type MockETHUSDAggregator struct { + address common.Address + abi abi.ABI + MockETHUSDAggregatorCaller + MockETHUSDAggregatorTransactor + MockETHUSDAggregatorFilterer +} + +type MockETHUSDAggregatorCaller struct { + contract *bind.BoundContract +} + +type MockETHUSDAggregatorTransactor struct { + contract *bind.BoundContract +} + +type MockETHUSDAggregatorFilterer struct { + contract *bind.BoundContract +} + +type MockETHUSDAggregatorSession struct { + Contract *MockETHUSDAggregator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type MockETHUSDAggregatorCallerSession struct { + Contract *MockETHUSDAggregatorCaller + CallOpts bind.CallOpts +} + +type MockETHUSDAggregatorTransactorSession struct { + Contract *MockETHUSDAggregatorTransactor + TransactOpts bind.TransactOpts +} + +type MockETHUSDAggregatorRaw struct { + Contract *MockETHUSDAggregator +} + +type MockETHUSDAggregatorCallerRaw struct { + Contract *MockETHUSDAggregatorCaller +} + +type MockETHUSDAggregatorTransactorRaw struct { + Contract *MockETHUSDAggregatorTransactor +} + +func NewMockETHUSDAggregator(address common.Address, backend bind.ContractBackend) (*MockETHUSDAggregator, error) { + abi, err := abi.JSON(strings.NewReader(MockETHUSDAggregatorABI)) + if err != nil { + return nil, err + } + contract, err := bindMockETHUSDAggregator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &MockETHUSDAggregator{address: address, abi: abi, MockETHUSDAggregatorCaller: MockETHUSDAggregatorCaller{contract: contract}, MockETHUSDAggregatorTransactor: MockETHUSDAggregatorTransactor{contract: contract}, MockETHUSDAggregatorFilterer: MockETHUSDAggregatorFilterer{contract: contract}}, nil +} + +func NewMockETHUSDAggregatorCaller(address common.Address, caller bind.ContractCaller) (*MockETHUSDAggregatorCaller, error) { + contract, err := bindMockETHUSDAggregator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &MockETHUSDAggregatorCaller{contract: contract}, nil +} + +func NewMockETHUSDAggregatorTransactor(address common.Address, transactor bind.ContractTransactor) (*MockETHUSDAggregatorTransactor, error) { + contract, err := bindMockETHUSDAggregator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &MockETHUSDAggregatorTransactor{contract: contract}, nil +} + +func NewMockETHUSDAggregatorFilterer(address common.Address, filterer bind.ContractFilterer) (*MockETHUSDAggregatorFilterer, error) { + contract, err := bindMockETHUSDAggregator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &MockETHUSDAggregatorFilterer{contract: contract}, nil +} + +func bindMockETHUSDAggregator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := MockETHUSDAggregatorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockETHUSDAggregator.Contract.MockETHUSDAggregatorCaller.contract.Call(opts, result, method, params...) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockETHUSDAggregator.Contract.MockETHUSDAggregatorTransactor.contract.Transfer(opts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockETHUSDAggregator.Contract.MockETHUSDAggregatorTransactor.contract.Transact(opts, method, params...) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MockETHUSDAggregator.Contract.contract.Call(opts, result, method, params...) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MockETHUSDAggregator.Contract.contract.Transfer(opts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MockETHUSDAggregator.Contract.contract.Transact(opts, method, params...) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCaller) Answer(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockETHUSDAggregator.contract.Call(opts, &out, "answer") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) Answer() (*big.Int, error) { + return _MockETHUSDAggregator.Contract.Answer(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerSession) Answer() (*big.Int, error) { + return _MockETHUSDAggregator.Contract.Answer(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCaller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _MockETHUSDAggregator.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) Decimals() (uint8, error) { + return _MockETHUSDAggregator.Contract.Decimals(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerSession) Decimals() (uint8, error) { + return _MockETHUSDAggregator.Contract.Decimals(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCaller) Description(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _MockETHUSDAggregator.contract.Call(opts, &out, "description") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) Description() (string, error) { + return _MockETHUSDAggregator.Contract.Description(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerSession) Description() (string, error) { + return _MockETHUSDAggregator.Contract.Description(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCaller) GetRoundData(opts *bind.CallOpts, arg0 *big.Int) (GetRoundData, + + error) { + var out []interface{} + err := _MockETHUSDAggregator.contract.Call(opts, &out, "getRoundData", arg0) + + outstruct := new(GetRoundData) + if err != nil { + return *outstruct, err + } + + outstruct.RoundId = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Ans = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.StartedAt = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.UpdatedAt = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.AnsweredInRound = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) GetRoundData(arg0 *big.Int) (GetRoundData, + + error) { + return _MockETHUSDAggregator.Contract.GetRoundData(&_MockETHUSDAggregator.CallOpts, arg0) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerSession) GetRoundData(arg0 *big.Int) (GetRoundData, + + error) { + return _MockETHUSDAggregator.Contract.GetRoundData(&_MockETHUSDAggregator.CallOpts, arg0) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCaller) LatestRoundData(opts *bind.CallOpts) (LatestRoundData, + + error) { + var out []interface{} + err := _MockETHUSDAggregator.contract.Call(opts, &out, "latestRoundData") + + outstruct := new(LatestRoundData) + if err != nil { + return *outstruct, err + } + + outstruct.RoundId = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Ans = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.StartedAt = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.UpdatedAt = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + outstruct.AnsweredInRound = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) LatestRoundData() (LatestRoundData, + + error) { + return _MockETHUSDAggregator.Contract.LatestRoundData(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerSession) LatestRoundData() (LatestRoundData, + + error) { + return _MockETHUSDAggregator.Contract.LatestRoundData(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCaller) Version(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _MockETHUSDAggregator.contract.Call(opts, &out, "version") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) Version() (*big.Int, error) { + return _MockETHUSDAggregator.Contract.Version(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorCallerSession) Version() (*big.Int, error) { + return _MockETHUSDAggregator.Contract.Version(&_MockETHUSDAggregator.CallOpts) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorTransactor) SetBlockTimestampDeduction(opts *bind.TransactOpts, _blockTimestampDeduction *big.Int) (*types.Transaction, error) { + return _MockETHUSDAggregator.contract.Transact(opts, "setBlockTimestampDeduction", _blockTimestampDeduction) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorSession) SetBlockTimestampDeduction(_blockTimestampDeduction *big.Int) (*types.Transaction, error) { + return _MockETHUSDAggregator.Contract.SetBlockTimestampDeduction(&_MockETHUSDAggregator.TransactOpts, _blockTimestampDeduction) +} + +func (_MockETHUSDAggregator *MockETHUSDAggregatorTransactorSession) SetBlockTimestampDeduction(_blockTimestampDeduction *big.Int) (*types.Transaction, error) { + return _MockETHUSDAggregator.Contract.SetBlockTimestampDeduction(&_MockETHUSDAggregator.TransactOpts, _blockTimestampDeduction) +} + +type GetRoundData struct { + RoundId *big.Int + Ans *big.Int + StartedAt *big.Int + UpdatedAt *big.Int + AnsweredInRound *big.Int +} +type LatestRoundData struct { + RoundId *big.Int + Ans *big.Int + StartedAt *big.Int + UpdatedAt *big.Int + AnsweredInRound *big.Int +} + +func (_MockETHUSDAggregator *MockETHUSDAggregator) Address() common.Address { + return _MockETHUSDAggregator.address +} + +type MockETHUSDAggregatorInterface interface { + Answer(opts *bind.CallOpts) (*big.Int, error) + + Decimals(opts *bind.CallOpts) (uint8, error) + + Description(opts *bind.CallOpts) (string, error) + + GetRoundData(opts *bind.CallOpts, arg0 *big.Int) (GetRoundData, + + error) + + LatestRoundData(opts *bind.CallOpts) (LatestRoundData, + + error) + + Version(opts *bind.CallOpts) (*big.Int, error) + + SetBlockTimestampDeduction(opts *bind.TransactOpts, _blockTimestampDeduction *big.Int) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go b/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go new file mode 100644 index 0000000000..f38435143b --- /dev/null +++ b/core/gethwrappers/generated/weth9_wrapper/weth9_wrapper.go @@ -0,0 +1,1010 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package weth9_wrapper + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var WETH9MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610114565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610114565b506002805460ff1916601217905534801561006f57600080fd5b506101d3565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561010f57600081815260208120601f850160051c810160208610156100ec5750805b601f850160051c820191505b8181101561010b578281556001016100f8565b5050505b505050565b81516001600160401b0381111561012d5761012d610075565b6101418161013b845461008b565b846100c5565b602080601f831160018114610176576000841561015e5750858301515b600019600386901b1c1916600185901b17855561010b565b600085815260208120601f198616915b828110156101a557888601518255948401946001909101908401610186565b50858210156101c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61099c80620001e36000396000f3fe6080604052600436106100cb5760003560e01c806340c10f1911610074578063a9059cbb1161004e578063a9059cbb14610225578063d0e30db014610245578063dd62ed3e1461024d57600080fd5b806340c10f19146101c357806370a08231146101e357806395d89b411461021057600080fd5b806323b872dd116100a557806323b872dd146101575780632e1a7d4d14610177578063313ce5671461019757600080fd5b806306fdde03146100df578063095ea7b31461010a57806318160ddd1461013a57600080fd5b366100da576100d8610285565b005b600080fd5b3480156100eb57600080fd5b506100f46102e0565b6040516101019190610785565b60405180910390f35b34801561011657600080fd5b5061012a61012536600461081a565b61036e565b6040519015158152602001610101565b34801561014657600080fd5b50475b604051908152602001610101565b34801561016357600080fd5b5061012a610172366004610844565b6103e8565b34801561018357600080fd5b506100d8610192366004610880565b610649565b3480156101a357600080fd5b506002546101b19060ff1681565b60405160ff9091168152602001610101565b3480156101cf57600080fd5b506100d86101de36600461081a565b61071c565b3480156101ef57600080fd5b506101496101fe366004610899565b60036020526000908152604090205481565b34801561021c57600080fd5b506100f461075a565b34801561023157600080fd5b5061012a61024036600461081a565b610767565b6100d861077b565b34801561025957600080fd5b506101496102683660046108b4565b600460209081526000928352604080842090915290825290205481565b33600090815260036020526040812080543492906102a4908490610916565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102ed90610929565b80601f016020809104026020016040519081016040528092919081815260200182805461031990610929565b80156103665780601f1061033b57610100808354040283529160200191610366565b820191906000526020600020905b81548152906001019060200180831161034957829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103d69086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812054821115610447576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104ad575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156105625773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561051c576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091528120805484929061055c90849061097c565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260408120805484929061059790849061097c565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080548492906105d1908490610916565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161063791815260200190565b60405180910390a35060019392505050565b33600090815260036020526040902054811115610692576040517ff4d678b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33600090815260036020526040812080548392906106b190849061097c565b9091555050604051339082156108fc029083906000818181858888f193505050501580156106e3573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054839290610751908490610916565b90915550505050565b600180546102ed90610929565b60006107743384846103e8565b9392505050565b610783610285565b565b600060208083528351808285015260005b818110156107b257858101830151858201604001528201610796565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461081557600080fd5b919050565b6000806040838503121561082d57600080fd5b610836836107f1565b946020939093013593505050565b60008060006060848603121561085957600080fd5b610862846107f1565b9250610870602085016107f1565b9150604084013590509250925092565b60006020828403121561089257600080fd5b5035919050565b6000602082840312156108ab57600080fd5b610774826107f1565b600080604083850312156108c757600080fd5b6108d0836107f1565b91506108de602084016107f1565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103e2576103e26108e7565b600181811c9082168061093d57607f821691505b602082108103610976577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103e2576103e26108e756fea164736f6c6343000813000a", +} + +var WETH9ABI = WETH9MetaData.ABI + +var WETH9Bin = WETH9MetaData.Bin + +func DeployWETH9(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *WETH9, error) { + parsed, err := WETH9MetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(WETH9Bin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &WETH9{address: address, abi: *parsed, WETH9Caller: WETH9Caller{contract: contract}, WETH9Transactor: WETH9Transactor{contract: contract}, WETH9Filterer: WETH9Filterer{contract: contract}}, nil +} + +type WETH9 struct { + address common.Address + abi abi.ABI + WETH9Caller + WETH9Transactor + WETH9Filterer +} + +type WETH9Caller struct { + contract *bind.BoundContract +} + +type WETH9Transactor struct { + contract *bind.BoundContract +} + +type WETH9Filterer struct { + contract *bind.BoundContract +} + +type WETH9Session struct { + Contract *WETH9 + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type WETH9CallerSession struct { + Contract *WETH9Caller + CallOpts bind.CallOpts +} + +type WETH9TransactorSession struct { + Contract *WETH9Transactor + TransactOpts bind.TransactOpts +} + +type WETH9Raw struct { + Contract *WETH9 +} + +type WETH9CallerRaw struct { + Contract *WETH9Caller +} + +type WETH9TransactorRaw struct { + Contract *WETH9Transactor +} + +func NewWETH9(address common.Address, backend bind.ContractBackend) (*WETH9, error) { + abi, err := abi.JSON(strings.NewReader(WETH9ABI)) + if err != nil { + return nil, err + } + contract, err := bindWETH9(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &WETH9{address: address, abi: abi, WETH9Caller: WETH9Caller{contract: contract}, WETH9Transactor: WETH9Transactor{contract: contract}, WETH9Filterer: WETH9Filterer{contract: contract}}, nil +} + +func NewWETH9Caller(address common.Address, caller bind.ContractCaller) (*WETH9Caller, error) { + contract, err := bindWETH9(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &WETH9Caller{contract: contract}, nil +} + +func NewWETH9Transactor(address common.Address, transactor bind.ContractTransactor) (*WETH9Transactor, error) { + contract, err := bindWETH9(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &WETH9Transactor{contract: contract}, nil +} + +func NewWETH9Filterer(address common.Address, filterer bind.ContractFilterer) (*WETH9Filterer, error) { + contract, err := bindWETH9(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &WETH9Filterer{contract: contract}, nil +} + +func bindWETH9(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := WETH9MetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_WETH9 *WETH9Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _WETH9.Contract.WETH9Caller.contract.Call(opts, result, method, params...) +} + +func (_WETH9 *WETH9Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WETH9.Contract.WETH9Transactor.contract.Transfer(opts) +} + +func (_WETH9 *WETH9Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _WETH9.Contract.WETH9Transactor.contract.Transact(opts, method, params...) +} + +func (_WETH9 *WETH9CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _WETH9.Contract.contract.Call(opts, result, method, params...) +} + +func (_WETH9 *WETH9TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WETH9.Contract.contract.Transfer(opts) +} + +func (_WETH9 *WETH9TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _WETH9.Contract.contract.Transact(opts, method, params...) +} + +func (_WETH9 *WETH9Caller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _WETH9.contract.Call(opts, &out, "allowance", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_WETH9 *WETH9Session) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _WETH9.Contract.Allowance(&_WETH9.CallOpts, arg0, arg1) +} + +func (_WETH9 *WETH9CallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _WETH9.Contract.Allowance(&_WETH9.CallOpts, arg0, arg1) +} + +func (_WETH9 *WETH9Caller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _WETH9.contract.Call(opts, &out, "balanceOf", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_WETH9 *WETH9Session) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _WETH9.Contract.BalanceOf(&_WETH9.CallOpts, arg0) +} + +func (_WETH9 *WETH9CallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _WETH9.Contract.BalanceOf(&_WETH9.CallOpts, arg0) +} + +func (_WETH9 *WETH9Caller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _WETH9.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_WETH9 *WETH9Session) Decimals() (uint8, error) { + return _WETH9.Contract.Decimals(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9CallerSession) Decimals() (uint8, error) { + return _WETH9.Contract.Decimals(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9Caller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _WETH9.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_WETH9 *WETH9Session) Name() (string, error) { + return _WETH9.Contract.Name(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9CallerSession) Name() (string, error) { + return _WETH9.Contract.Name(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9Caller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _WETH9.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_WETH9 *WETH9Session) Symbol() (string, error) { + return _WETH9.Contract.Symbol(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9CallerSession) Symbol() (string, error) { + return _WETH9.Contract.Symbol(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _WETH9.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_WETH9 *WETH9Session) TotalSupply() (*big.Int, error) { + return _WETH9.Contract.TotalSupply(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9CallerSession) TotalSupply() (*big.Int, error) { + return _WETH9.Contract.TotalSupply(&_WETH9.CallOpts) +} + +func (_WETH9 *WETH9Transactor) Approve(opts *bind.TransactOpts, guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.contract.Transact(opts, "approve", guy, wad) +} + +func (_WETH9 *WETH9Session) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Approve(&_WETH9.TransactOpts, guy, wad) +} + +func (_WETH9 *WETH9TransactorSession) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Approve(&_WETH9.TransactOpts, guy, wad) +} + +func (_WETH9 *WETH9Transactor) Deposit(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WETH9.contract.Transact(opts, "deposit") +} + +func (_WETH9 *WETH9Session) Deposit() (*types.Transaction, error) { + return _WETH9.Contract.Deposit(&_WETH9.TransactOpts) +} + +func (_WETH9 *WETH9TransactorSession) Deposit() (*types.Transaction, error) { + return _WETH9.Contract.Deposit(&_WETH9.TransactOpts) +} + +func (_WETH9 *WETH9Transactor) Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) { + return _WETH9.contract.Transact(opts, "mint", account, amount) +} + +func (_WETH9 *WETH9Session) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Mint(&_WETH9.TransactOpts, account, amount) +} + +func (_WETH9 *WETH9TransactorSession) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Mint(&_WETH9.TransactOpts, account, amount) +} + +func (_WETH9 *WETH9Transactor) Transfer(opts *bind.TransactOpts, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.contract.Transact(opts, "transfer", dst, wad) +} + +func (_WETH9 *WETH9Session) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Transfer(&_WETH9.TransactOpts, dst, wad) +} + +func (_WETH9 *WETH9TransactorSession) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Transfer(&_WETH9.TransactOpts, dst, wad) +} + +func (_WETH9 *WETH9Transactor) TransferFrom(opts *bind.TransactOpts, src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.contract.Transact(opts, "transferFrom", src, dst, wad) +} + +func (_WETH9 *WETH9Session) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.TransferFrom(&_WETH9.TransactOpts, src, dst, wad) +} + +func (_WETH9 *WETH9TransactorSession) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.TransferFrom(&_WETH9.TransactOpts, src, dst, wad) +} + +func (_WETH9 *WETH9Transactor) Withdraw(opts *bind.TransactOpts, wad *big.Int) (*types.Transaction, error) { + return _WETH9.contract.Transact(opts, "withdraw", wad) +} + +func (_WETH9 *WETH9Session) Withdraw(wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Withdraw(&_WETH9.TransactOpts, wad) +} + +func (_WETH9 *WETH9TransactorSession) Withdraw(wad *big.Int) (*types.Transaction, error) { + return _WETH9.Contract.Withdraw(&_WETH9.TransactOpts, wad) +} + +func (_WETH9 *WETH9Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _WETH9.contract.RawTransact(opts, nil) +} + +func (_WETH9 *WETH9Session) Receive() (*types.Transaction, error) { + return _WETH9.Contract.Receive(&_WETH9.TransactOpts) +} + +func (_WETH9 *WETH9TransactorSession) Receive() (*types.Transaction, error) { + return _WETH9.Contract.Receive(&_WETH9.TransactOpts) +} + +type WETH9ApprovalIterator struct { + Event *WETH9Approval + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *WETH9ApprovalIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(WETH9Approval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(WETH9Approval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *WETH9ApprovalIterator) Error() error { + return it.fail +} + +func (it *WETH9ApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type WETH9Approval struct { + Src common.Address + Guy common.Address + Wad *big.Int + Raw types.Log +} + +func (_WETH9 *WETH9Filterer) FilterApproval(opts *bind.FilterOpts, src []common.Address, guy []common.Address) (*WETH9ApprovalIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var guyRule []interface{} + for _, guyItem := range guy { + guyRule = append(guyRule, guyItem) + } + + logs, sub, err := _WETH9.contract.FilterLogs(opts, "Approval", srcRule, guyRule) + if err != nil { + return nil, err + } + return &WETH9ApprovalIterator{contract: _WETH9.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +func (_WETH9 *WETH9Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *WETH9Approval, src []common.Address, guy []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var guyRule []interface{} + for _, guyItem := range guy { + guyRule = append(guyRule, guyItem) + } + + logs, sub, err := _WETH9.contract.WatchLogs(opts, "Approval", srcRule, guyRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(WETH9Approval) + if err := _WETH9.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_WETH9 *WETH9Filterer) ParseApproval(log types.Log) (*WETH9Approval, error) { + event := new(WETH9Approval) + if err := _WETH9.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type WETH9DepositIterator struct { + Event *WETH9Deposit + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *WETH9DepositIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(WETH9Deposit) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(WETH9Deposit) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *WETH9DepositIterator) Error() error { + return it.fail +} + +func (it *WETH9DepositIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type WETH9Deposit struct { + Dst common.Address + Wad *big.Int + Raw types.Log +} + +func (_WETH9 *WETH9Filterer) FilterDeposit(opts *bind.FilterOpts, dst []common.Address) (*WETH9DepositIterator, error) { + + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _WETH9.contract.FilterLogs(opts, "Deposit", dstRule) + if err != nil { + return nil, err + } + return &WETH9DepositIterator{contract: _WETH9.contract, event: "Deposit", logs: logs, sub: sub}, nil +} + +func (_WETH9 *WETH9Filterer) WatchDeposit(opts *bind.WatchOpts, sink chan<- *WETH9Deposit, dst []common.Address) (event.Subscription, error) { + + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _WETH9.contract.WatchLogs(opts, "Deposit", dstRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(WETH9Deposit) + if err := _WETH9.contract.UnpackLog(event, "Deposit", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_WETH9 *WETH9Filterer) ParseDeposit(log types.Log) (*WETH9Deposit, error) { + event := new(WETH9Deposit) + if err := _WETH9.contract.UnpackLog(event, "Deposit", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type WETH9TransferIterator struct { + Event *WETH9Transfer + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *WETH9TransferIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(WETH9Transfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(WETH9Transfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *WETH9TransferIterator) Error() error { + return it.fail +} + +func (it *WETH9TransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type WETH9Transfer struct { + Src common.Address + Dst common.Address + Wad *big.Int + Raw types.Log +} + +func (_WETH9 *WETH9Filterer) FilterTransfer(opts *bind.FilterOpts, src []common.Address, dst []common.Address) (*WETH9TransferIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _WETH9.contract.FilterLogs(opts, "Transfer", srcRule, dstRule) + if err != nil { + return nil, err + } + return &WETH9TransferIterator{contract: _WETH9.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +func (_WETH9 *WETH9Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *WETH9Transfer, src []common.Address, dst []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _WETH9.contract.WatchLogs(opts, "Transfer", srcRule, dstRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(WETH9Transfer) + if err := _WETH9.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_WETH9 *WETH9Filterer) ParseTransfer(log types.Log) (*WETH9Transfer, error) { + event := new(WETH9Transfer) + if err := _WETH9.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type WETH9WithdrawalIterator struct { + Event *WETH9Withdrawal + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *WETH9WithdrawalIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(WETH9Withdrawal) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(WETH9Withdrawal) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *WETH9WithdrawalIterator) Error() error { + return it.fail +} + +func (it *WETH9WithdrawalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type WETH9Withdrawal struct { + Src common.Address + Wad *big.Int + Raw types.Log +} + +func (_WETH9 *WETH9Filterer) FilterWithdrawal(opts *bind.FilterOpts, src []common.Address) (*WETH9WithdrawalIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _WETH9.contract.FilterLogs(opts, "Withdrawal", srcRule) + if err != nil { + return nil, err + } + return &WETH9WithdrawalIterator{contract: _WETH9.contract, event: "Withdrawal", logs: logs, sub: sub}, nil +} + +func (_WETH9 *WETH9Filterer) WatchWithdrawal(opts *bind.WatchOpts, sink chan<- *WETH9Withdrawal, src []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _WETH9.contract.WatchLogs(opts, "Withdrawal", srcRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(WETH9Withdrawal) + if err := _WETH9.contract.UnpackLog(event, "Withdrawal", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_WETH9 *WETH9Filterer) ParseWithdrawal(log types.Log) (*WETH9Withdrawal, error) { + event := new(WETH9Withdrawal) + if err := _WETH9.contract.UnpackLog(event, "Withdrawal", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_WETH9 *WETH9) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _WETH9.abi.Events["Approval"].ID: + return _WETH9.ParseApproval(log) + case _WETH9.abi.Events["Deposit"].ID: + return _WETH9.ParseDeposit(log) + case _WETH9.abi.Events["Transfer"].ID: + return _WETH9.ParseTransfer(log) + case _WETH9.abi.Events["Withdrawal"].ID: + return _WETH9.ParseWithdrawal(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (WETH9Approval) Topic() common.Hash { + return common.HexToHash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925") +} + +func (WETH9Deposit) Topic() common.Hash { + return common.HexToHash("0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c") +} + +func (WETH9Transfer) Topic() common.Hash { + return common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") +} + +func (WETH9Withdrawal) Topic() common.Hash { + return common.HexToHash("0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65") +} + +func (_WETH9 *WETH9) Address() common.Address { + return _WETH9.address +} + +type WETH9Interface interface { + Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) + + BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) + + Decimals(opts *bind.CallOpts) (uint8, error) + + Name(opts *bind.CallOpts) (string, error) + + Symbol(opts *bind.CallOpts) (string, error) + + TotalSupply(opts *bind.CallOpts) (*big.Int, error) + + Approve(opts *bind.TransactOpts, guy common.Address, wad *big.Int) (*types.Transaction, error) + + Deposit(opts *bind.TransactOpts) (*types.Transaction, error) + + Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) + + Transfer(opts *bind.TransactOpts, dst common.Address, wad *big.Int) (*types.Transaction, error) + + TransferFrom(opts *bind.TransactOpts, src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) + + Withdraw(opts *bind.TransactOpts, wad *big.Int) (*types.Transaction, error) + + Receive(opts *bind.TransactOpts) (*types.Transaction, error) + + FilterApproval(opts *bind.FilterOpts, src []common.Address, guy []common.Address) (*WETH9ApprovalIterator, error) + + WatchApproval(opts *bind.WatchOpts, sink chan<- *WETH9Approval, src []common.Address, guy []common.Address) (event.Subscription, error) + + ParseApproval(log types.Log) (*WETH9Approval, error) + + FilterDeposit(opts *bind.FilterOpts, dst []common.Address) (*WETH9DepositIterator, error) + + WatchDeposit(opts *bind.WatchOpts, sink chan<- *WETH9Deposit, dst []common.Address) (event.Subscription, error) + + ParseDeposit(log types.Log) (*WETH9Deposit, error) + + FilterTransfer(opts *bind.FilterOpts, src []common.Address, dst []common.Address) (*WETH9TransferIterator, error) + + WatchTransfer(opts *bind.WatchOpts, sink chan<- *WETH9Transfer, src []common.Address, dst []common.Address) (event.Subscription, error) + + ParseTransfer(log types.Log) (*WETH9Transfer, error) + + FilterWithdrawal(opts *bind.FilterOpts, src []common.Address) (*WETH9WithdrawalIterator, error) + + WatchWithdrawal(opts *bind.WatchOpts, sink chan<- *WETH9Withdrawal, src []common.Address) (event.Subscription, error) + + ParseWithdrawal(log types.Log) (*WETH9Withdrawal, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index e891332936..e3cf0db7df 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -8,12 +8,12 @@ automation_compatible_utils: ../../contracts/solc/v0.8.19/AutomationCompatibleUt automation_consumer_benchmark: ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.bin f52c76f1aaed4be541d82d97189d70f5aa027fc9838037dd7a7d21910c8c488e automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin 15ae0c367297955fdab4b552dbb10e1f2be80a8fde0efec4a4d398693e9d72b5 automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42 -automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 05dfc1601a6e8a43d98c982b5cb1ad1060b49948dc0c8ccd829ca2c9f6d9430e +automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin 41f4b045cb783a8ad6e786b54216cc3666101abe75851784252e71aae3b00a99 automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 73b5cc3ece642abbf6f2a4c9188335b71404f4dd0ad10b761390b6397af6f1c8 automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin fbf6f6cf4e6858855ff5da847c3baa4859dd997cfae51f2fa0651e4fa15b92c9 -automation_registry_logic_c_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicC2_3/AutomationRegistryLogicC2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicC2_3/AutomationRegistryLogicC2_3.bin 3ee51aa2f946b9fe3583b4a8526d29721339f96774e410bd37ddfe8184a63701 +automation_registry_logic_c_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicC2_3/AutomationRegistryLogicC2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicC2_3/AutomationRegistryLogicC2_3.bin 6bfe0f54fa7a587a83b6981ffdef28b3cb5e24cae1c95becdf59eed21147d289 automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin f8f920a225fdb1e36948dd95bae3aa46ecc2b01fd113480e111960b5e5f95624 automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5 @@ -32,7 +32,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723 gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8 i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b -i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin d240ee2e5d66cc49dd11008ec405c97605d53e151b7c80b3518ffeb412845d19 +i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 06cc87c122452f63fbe84f65329978f30281613be0caa261e53503d94763e921 i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 @@ -55,6 +55,7 @@ log_emitter: ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contra log_triggered_streams_lookup_wrapper: ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin 920fff3b662909f12ed11b47d168036ffa74ad52070a94e2fa26cdad5e428b4e log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin 42426bbb83f96dfbe55fc576d6c65020eaeed690e2289cf99b0c4aa810a5f4ec mock_aggregator_proxy: ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin b16c108f3dd384c342ddff5e94da7c0a8d39d1be5e3d8f2cf61ecc7f0e50ff42 +mock_ethusd_aggregator_wrapper: ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.abi ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.bin b9b361f502d2aad32311c60ca86b071de93a024ac488bcfa19725d368cd05d61 offchain_aggregator_wrapper: OffchainAggregator/OffchainAggregator.abi - 5c8d6562e94166d4790f1ee6e4321d359d9f7262e6c5452a712b1f1c896f45cf operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin 88e6baa5d9b255eea02616fbcb2cbe21a25ab46adeb6395f6289d169dec949ae operator_wrapper: ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin 23c3888eaa7259e6adf2153d09abae8f4b1987dc44200363faab1e65483f32d5 @@ -115,3 +116,4 @@ vrfv2plus_reverting_example: ../../contracts/solc/v0.8.19/VRFV2PlusRevertingExam vrfv2plus_wrapper: ../../contracts/solc/v0.8.19/VRFV2PlusWrapper/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapper/VRFV2PlusWrapper.bin 004733665a250081153e8878c0621461fea65a2d3b4905269cbd79a0966f211e vrfv2plus_wrapper_consumer_example: ../../contracts/solc/v0.8.19/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.bin aeb0c681fa264f90971f65cba1e8d41064948070b217c8204a80ac95e1fa2294 vrfv2plus_wrapper_load_test_consumer: ../../contracts/solc/v0.8.19/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.bin 5ca0223d3f6f6073ddfee4f9ddca13ea5f87297eb5f800359d7a1c41d04b6776 +weth9_wrapper: ../../contracts/solc/v0.8.19/WETH9/WETH9.abi ../../contracts/solc/v0.8.19/WETH9/WETH9.bin 7f600a1de0c02a071cb13bcf9eb1dbf11c3e3eccd1e78ed4b4ecb2960f2bb020 diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index fdbd067733..829f79c91d 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -57,6 +57,8 @@ package gethwrappers //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.abi ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.bin ScrollModule scroll_module //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin IChainModule i_chain_module //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin IAutomationV21PlusCommon i_automation_v21_plus_common +//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.abi ../../contracts/solc/v0.8.19/MockETHUSDAggregator/MockETHUSDAggregator.bin MockETHUSDAggregator mock_ethusd_aggregator_wrapper +//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/WETH9/WETH9.abi ../../contracts/solc/v0.8.19/WETH9/WETH9.bin WETH9 weth9_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.abi ../../contracts/solc/v0.8.16/ILogAutomation/ILogAutomation.bin ILogAutomation i_log_automation //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin AutomationForwarderLogic automation_forwarder_logic diff --git a/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go b/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go new file mode 100644 index 0000000000..bb92001085 --- /dev/null +++ b/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go @@ -0,0 +1,2292 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package capabilities_registry + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type CapabilitiesRegistryCapability struct { + LabelledName string + Version string + CapabilityType uint8 + ResponseType uint8 + ConfigurationContract common.Address +} + +type CapabilitiesRegistryCapabilityConfiguration struct { + CapabilityId [32]byte + Config []byte +} + +type CapabilitiesRegistryCapabilityInfo struct { + HashedId [32]byte + LabelledName string + Version string + CapabilityType uint8 + ResponseType uint8 + ConfigurationContract common.Address + IsDeprecated bool +} + +type CapabilitiesRegistryDONInfo struct { + Id uint32 + ConfigCount uint32 + F uint8 + IsPublic bool + AcceptsWorkflows bool + NodeP2PIds [][32]byte + CapabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration +} + +type CapabilitiesRegistryNodeInfo struct { + NodeOperatorId uint32 + ConfigCount uint32 + WorkflowDONId uint32 + Signer [32]byte + P2pId [32]byte + HashedCapabilityIds [][32]byte + CapabilitiesDONIds []*big.Int +} + +type CapabilitiesRegistryNodeOperator struct { + Admin common.Address + Name string +} + +type CapabilitiesRegistryNodeParams struct { + NodeOperatorId uint32 + Signer [32]byte + P2pId [32]byte + HashedCapabilityIds [][32]byte +} + +var CapabilitiesRegistryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"CapabilityRequiredByDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfCapabilitiesDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfWorkflowDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilitiesRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeInfo\",\"name\":\"nodeInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6150f680620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635e65e309116100ee5780638da5cb5b11610097578063d8bc7b6811610071578063d8bc7b68146103f6578063ddbe4f8214610409578063e29581aa1461041e578063f2fde38b1461043357600080fd5b80638da5cb5b1461039b5780639cb7c5f4146103c3578063d59a79f6146103e357600080fd5b806373ac22b4116100c857806373ac22b41461036d57806379ba50971461038057806386fa42461461038857600080fd5b80635e65e3091461033257806366acaa3314610345578063715f52951461035a57600080fd5b8063235374051161015b578063398f377311610135578063398f3773146102cb5780633f2a13c9146102de57806350c946fe146102ff5780635d83d9671461031f57600080fd5b80632353740514610285578063275459f2146102a55780632c01a1e8146102b857600080fd5b80631d05394c1161018c5780631d05394c1461023b578063214502431461025057806322bdbcbc1461026557600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613e8b565b610446565b6040519081526020015b60405180910390f35b6101ec6101e7366004613eef565b61047a565b60405190151581526020016101d0565b604080518082018252601a81527f4361706162696c6974696573526567697374727920312e302e30000000000000602082015290516101d09190613f76565b61024e610249366004613fce565b610487565b005b61025861069c565b6040516101d09190614150565b6102786102733660046141eb565b6107f9565b6040516101d09190614243565b6102986102933660046141eb565b6108e6565b6040516101d09190614256565b61024e6102b3366004613fce565b61092a565b61024e6102c6366004613fce565b610a01565b61024e6102d9366004613fce565b610c9d565b6102f16102ec366004614269565b610e5c565b6040516101d0929190614293565b61031261030d366004613eef565b611048565b6040516101d09190614358565b61024e61032d366004613fce565b611122565b61024e610340366004613fce565b611217565b61034d61193f565b6040516101d0919061436b565b61024e610368366004613fce565b611b22565b61024e61037b366004613fce565b611bd4565b61024e6120a2565b61024e6103963660046143e0565b61219f565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6103d66103d1366004613eef565b6124df565b6040516101d0919061452f565b61024e6103f1366004614561565b61271a565b61024e610404366004614616565b6127e3565b6104116128ad565b6040516101d091906146bb565b6104266129a1565b6040516101d09190614730565b61024e6104413660046147c9565b612aaa565b6000828260405160200161045b929190614293565b6040516020818303038152906040528051906020012090505b92915050565b6000610474600583612abe565b61048f612ad9565b60005b818110156106975760008383838181106104ae576104ae6147e4565b90506020020160208101906104c391906141eb565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61051b83612b5c565b8110156105bb57811561057157600c60006105368584612b66565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556105b3565b6105b18663ffffffff16600c60006105928588612b6690919063ffffffff16565b8152602001908152602001600020600401612b7290919063ffffffff16565b505b600101610512565b508354640100000000900463ffffffff16600003610612576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff861660048201526024015b60405180910390fd5b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a15050505050806001019050610492565b505050565b600e54606090640100000000900463ffffffff1660006106bd600183614842565b63ffffffff1667ffffffffffffffff8111156106db576106db613d25565b60405190808252806020026020018201604052801561076257816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106f95790505b509050600060015b8363ffffffff168163ffffffff1610156107d65763ffffffff8082166000908152600d602052604090205416156107ce576107a481612b7e565b8383815181106107b6576107b66147e4565b6020026020010181905250816107cb9061485f565b91505b60010161076a565b506107e2600184614842565b63ffffffff1681146107f2578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161085d90614897565b80601f016020809104026020016040519081016040528092919081815260200182805461088990614897565b80156108d65780601f106108ab576101008083540402835291602001916108d6565b820191906000526020600020905b8154815290600101906020018083116108b957829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261047482612b7e565b610932612ad9565b60005b63ffffffff811682111561069757600083838363ffffffff1681811061095d5761095d6147e4565b905060200201602081019061097291906141eb565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559192506109bd6001830182613cb8565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a2506109fa816148ea565b9050610935565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110610a3b57610a3b6147e4565b602090810292909201356000818152600c90935260409092206001810154929350919050610a98576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610609565b6000610aa682600401612b5c565b1115610afb57610ab96004820184612b66565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610609565b805468010000000000000000900463ffffffff1615610b635780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610609565b83158015610b9d5750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610bd6576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6001810154610be790600790612b72565b506002810154610bf990600990612b72565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815560018101829055600281018290559060048201818181610c4e8282613cf2565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610c8591815260200190565b60405180910390a15050600101610a1f565b50505050565b610ca5612ad9565b60005b81811015610697576000838383818110610cc457610cc46147e4565b9050602002810190610cd6919061490d565b610cdf9061494b565b805190915073ffffffffffffffffffffffffffffffffffffffff16610d30576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610dbc9082614a05565b5050600e8054909150600090610dd79063ffffffff166148ea565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610e4a9190613f76565b60405180910390a35050600101610ca8565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610eae90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054610eda90614897565b8015610f275780601f10610efc57610100808354040283529160200191610f27565b820191906000526020600020905b815481529060010190602001808311610f0a57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff1615915061103a905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015610ff1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110379190810190614b1f565b90505b9093509150505b9250929050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c08101919091526040805160e0810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152835260030190529190912060a08201906110f790612e49565b815260200161111a600c6000868152602001908152602001600020600401612e49565b905292915050565b61112a612ad9565b60005b81811015610697576000838383818110611149576111496147e4565b905060200201359050611166816003612abe90919063ffffffff16565b61119f576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b6111aa600582612e56565b6111e3576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a25060010161112d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110611251576112516147e4565b90506020028101906112639190614b8d565b61126c90614bc1565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549596509394919390928401916112c290614897565b80601f01602080910402602001604051908101604052809291908181526020018280546112ee90614897565b801561133b5780601f106113105761010080835404028352916020019161133b565b820191906000526020600020905b81548152906001019060200180831161131e57829003601f168201915b50505050508152505090508315801561136b5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156113a4576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6040808301516000908152600c6020522060018101546113f85782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b6020830151611433576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154602084015181146114b457602084015161145490600790612abe565b1561148b576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018301556114a0600782612b72565b5060208401516114b290600790612e56565b505b606084015180516000036114f657806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b8254600090849060049061151790640100000000900463ffffffff166148ea565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b82518110156115fc5761156f838281518110611557576115576147e4565b60200260200101516003612abe90919063ffffffff16565b6115a757826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b6115f38382815181106115bc576115bc6147e4565b60200260200101518660030160008563ffffffff1663ffffffff168152602001908152602001600020612e5690919063ffffffff16565b50600101611539565b50835468010000000000000000900463ffffffff16801561175d5763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561169157602002820191906000526020600020905b81548152602001906001019080831161167d575b5050505050905060005b815181101561175a576116f08282815181106116b9576116b96147e4565b60200260200101518860030160008763ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b61175257818181518110611706576117066147e4565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060992919091825263ffffffff16602082015260400190565b60010161169b565b50505b600061176b86600401612e49565b905060005b81518163ffffffff1610156118b1576000828263ffffffff1681518110611799576117996147e4565b60209081029190910181015163ffffffff8082166000908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561182057602002820191906000526020600020905b81548152602001906001019080831161180c575b5050505050905060005b815181101561189d5761187f828281518110611848576118486147e4565b60200260200101518b60030160008a63ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b61189557818181518110611706576117066147e4565b60010161182a565b505050806118aa906148ea565b9050611770565b50875186547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811787556040808a0151600289018190556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050611235565b600e5460609063ffffffff166000611958600183614842565b63ffffffff1667ffffffffffffffff81111561197657611976613d25565b6040519080825280602002602001820160405280156119bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816119945790505b509050600060015b8363ffffffff168163ffffffff161015611b0c5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611b045763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611a5890614897565b80601f0160208091040260200160405190810160405280929190818152602001828054611a8490614897565b8015611ad15780601f10611aa657610100808354040283529160200191611ad1565b820191906000526020600020905b815481529060010190602001808311611ab457829003601f168201915b505050505081525050838381518110611aec57611aec6147e4565b602002602001018190525081611b019061485f565b91505b6001016119c4565b50600e546107e29060019063ffffffff16614842565b611b2a612ad9565b60005b81811015610697576000838383818110611b4957611b496147e4565b9050602002810190611b5b9190614cd8565b611b6490614d1b565b90506000611b7a82600001518360200151610446565b9050611b87600382612e56565b611bc0576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b611bca8183612e62565b5050600101611b2d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110611c0e57611c0e6147e4565b9050602002810190611c209190614b8d565b611c2990614bc1565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191611c7f90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054611cab90614897565b8015611cf85780601f10611ccd57610100808354040283529160200191611cf8565b820191906000526020600020905b815481529060010190602001808311611cdb57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611d5e5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610609565b83158015611d835750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611dbc576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6040808301516000908152600c60205220600181015415611e115782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b6040830151611e545782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b60208301511580611e7157506020830151611e7190600790612abe565b15611ea8576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611eea57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b81548290600490611f0890640100000000900463ffffffff166148ea565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b8251811015611fde57611f51838281518110611557576115576147e4565b611f8957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b611fd5838281518110611f9e57611f9e6147e4565b60200260200101518560030160008563ffffffff1663ffffffff168152602001908152602001600020612e5690919063ffffffff16565b50600101611f33565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff918216178455604086015160028501556020860151600185018190556120349160079190612e5616565b50604085015161204690600990612e56565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611bf2565b60015473ffffffffffffffffffffffffffffffffffffffff163314612123576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610609565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b8281146121e2576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610609565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156124d757600086868381811061221a5761221a6147e4565b905060200201602081019061222f91906141eb565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661229e576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610609565b60008686858181106122b2576122b26147e4565b90506020028101906122c4919061490d565b6122cd9061494b565b805190915073ffffffffffffffffffffffffffffffffffffffff1661231e576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061235b57503373ffffffffffffffffffffffffffffffffffffffff861614155b15612394576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061241057506020808201516040516123cd9201613f76565b60405160208183030381529060405280519060200120826001016040516020016123f79190614dc1565b6040516020818303038152906040528051906020012014155b156124c957805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020810151600183019061246a9082614a05565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516124c09190613f76565b60405180910390a35b5050508060010190506121fe565b505050505050565b6125206040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e0810182528381526000848152600260209081529290208054919283019161254c90614897565b80601f016020809104026020016040519081016040528092919081815260200182805461257890614897565b80156125c55780601f1061259a576101008083540402835291602001916125c5565b820191906000526020600020905b8154815290600101906020018083116125a857829003601f168201915b505050505081526020016002600085815260200190815260200160002060010180546125f090614897565b80601f016020809104026020016040519081016040528092919081815260200182805461261c90614897565b80156126695780601f1061263e57610100808354040283529160200191612669565b820191906000526020600020905b81548152906001019060200180831161264c57829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff16600381111561269b5761269b61444c565b815260008481526002602081815260409092200154910190610100900460ff1660018111156126cc576126cc61444c565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff169083015201612710600585612abe565b1515905292915050565b612722612ad9565b63ffffffff8089166000908152600d6020526040812054640100000000900490911690819003612786576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610609565b6127d8888888886040518060a001604052808f63ffffffff168152602001876127ae906148ea565b97508763ffffffff1681526020018a1515815260200189151581526020018860ff168152506130f6565b505050505050505050565b6127eb612ad9565b600e805460009164010000000090910463ffffffff1690600461280d836148ea565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff841660808201529091506128a39089908990899089906130f6565b5050505050505050565b606060006128bb6003612e49565b90506000815167ffffffffffffffff8111156128d9576128d9613d25565b60405190808252806020026020018201604052801561294b57816020015b6129386040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b8152602001906001900390816128f75790505b50905060005b82518110156107f25761297c83828151811061296f5761296f6147e4565b60200260200101516124df565b82828151811061298e5761298e6147e4565b6020908102919091010152600101612951565b606060006129af6009612e49565b90506000815167ffffffffffffffff8111156129cd576129cd613d25565b604051908082528060200260200182016040528015612a5457816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816129eb5790505b50905060005b82518110156107f257612a85838281518110612a7857612a786147e4565b6020026020010151611048565b828281518110612a9757612a976147e4565b6020908102919091010152600101612a5a565b612ab2612ad9565b612abb8161391a565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612b5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610609565b565b6000610474825490565b6000612ad28383613a0f565b6000612ad28383613a39565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612c2f57602002820191906000526020600020905b815481526020019060010190808311612c1b575b505050505090506000815167ffffffffffffffff811115612c5257612c52613d25565b604051908082528060200260200182016040528015612c9857816020015b604080518082019091526000815260606020820152815260200190600190039081612c705790505b50905060005b8151811015612db0576040518060400160405280848381518110612cc457612cc46147e4565b60200260200101518152602001856003016000868581518110612ce957612ce96147e4565b602002602001015181526020019081526020016000208054612d0a90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054612d3690614897565b8015612d835780601f10612d5857610100808354040283529160200191612d83565b820191906000526020600020905b815481529060010190602001808311612d6657829003601f168201915b5050505050815250828281518110612d9d57612d9d6147e4565b6020908102919091010152600101612c9e565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a08101612e3785612e49565b81526020019190915295945050505050565b60606000612ad283613b2c565b6000612ad28383613b88565b608081015173ffffffffffffffffffffffffffffffffffffffff1615612fb057608081015173ffffffffffffffffffffffffffffffffffffffff163b1580612f5b575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa158015612f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f599190614e6f565b155b15612fb05760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610609565b600082815260026020526040902081518291908190612fcf9082614a05565b5060208201516001820190612fe49082614a05565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156130265761302661444c565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600181111561306d5761306d61444c565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613148575060808201518590613143906001614e8c565b60ff16115b156131915760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610609565b6001826020015163ffffffff16111561327957815163ffffffff166000908152600d6020908152604082209084015160019182019183916131d29190614842565b63ffffffff1663ffffffff168152602001908152602001600020905060005b6131fa82612b5c565b81101561327657613229846000015163ffffffff16600c60006105928587600001612b6690919063ffffffff16565b50600c60006132388484612b66565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556001016131f1565b50505b60005b858110156134b3576132a9878783818110613299576132996147e4565b8592602090910201359050612e56565b61330a5782518787838181106132c1576132c16147e4565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b82606001511561346157825163ffffffff16600c6000898985818110613332576133326147e4565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906133ac5750600c600088888481811061337d5761337d6147e4565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561340e5782518787838181106133c5576133c56147e4565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b8251600c6000898985818110613426576134266147e4565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff1602179055506134ab565b82516134a99063ffffffff16600c60008a8a86818110613483576134836147e4565b905060200201358152602001908152602001600020600401612e5690919063ffffffff16565b505b60010161327c565b5060005b8381101561378f57368585838181106134d2576134d26147e4565b90506020028101906134e4919061490d565b90506134f260038235612abe565b61352b576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b61353760058235612abe565b15613571576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b803560009081526003840160205260408120805461358e90614897565b905011156135da5783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610609565b60005b878110156136e4576136818235600c60008c8c86818110613600576136006147e4565b9050602002013581526020019081526020016000206003016000600c60008e8e88818110613630576136306147e4565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b6136dc57888882818110613697576136976147e4565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610609565b6001016135dd565b506002830180546001810182556000918252602091829020833591015561370d90820182614ea5565b8235600090815260038601602052604090209161372b919083614f0a565b50835160208086015161378692918435908c908c9061374c90880188614ea5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613bd792505050565b506001016134b7565b50604080830151835163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606086015186518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080860151865183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055918501805186518316845292849020805493909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9093169290921790558351905191517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c15817036519261390a929163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610609565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613a2657613a266147e4565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613b22576000613a5d600183615025565b8554909150600090613a7190600190615025565b9050818114613ad6576000866000018281548110613a9157613a916147e4565b9060005260206000200154905080876000018481548110613ab457613ab46147e4565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613ae757613ae7615038565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610474565b6000915050610474565b606081600001805480602002602001604051908101604052809291908181526020018280548015613b7c57602002820191906000526020600020905b815481526020019060010190808311613b68575b50505050509050919050565b6000818152600183016020526040812054613bcf57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610474565b506000610474565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156124d757600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613c7e908690869086908b908d90600401615067565b600060405180830381600087803b158015613c9857600080fd5b505af1158015613cac573d6000803e3d6000fd5b50505050505050505050565b508054613cc490614897565b6000825580601f10613cd4575050565b601f016020900490600052602060002090810190612abb9190613d0c565b5080546000825590600052602060002090810190612abb91905b5b80821115613d215760008155600101613d0d565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613d7757613d77613d25565b60405290565b60405160a0810167ffffffffffffffff81118282101715613d7757613d77613d25565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613de757613de7613d25565b604052919050565b600067ffffffffffffffff821115613e0957613e09613d25565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613e4657600080fd5b8135613e59613e5482613def565b613da0565b818152846020838601011115613e6e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613e9e57600080fd5b823567ffffffffffffffff80821115613eb657600080fd5b613ec286838701613e35565b93506020850135915080821115613ed857600080fd5b50613ee585828601613e35565b9150509250929050565b600060208284031215613f0157600080fd5b5035919050565b60005b83811015613f23578181015183820152602001613f0b565b50506000910152565b60008151808452613f44816020860160208601613f08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612ad26020830184613f2c565b60008083601f840112613f9b57600080fd5b50813567ffffffffffffffff811115613fb357600080fd5b6020830191508360208260051b850101111561104157600080fd5b60008060208385031215613fe157600080fd5b823567ffffffffffffffff811115613ff857600080fd5b61400485828601613f89565b90969095509350505050565b60008151808452602080850194506020840160005b8381101561404157815187529582019590820190600101614025565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156140c9578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526140b581860183613f2c565b9a86019a9450505090830190600101614069565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261412e60e0850182614010565b905060c083015184820360c0860152614147828261404c565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526141b38583516140d6565b94509285019290850190600101614179565b5092979650505050505050565b803563ffffffff811681146141e657600080fd5b919050565b6000602082840312156141fd57600080fd5b612ad2826141d2565b73ffffffffffffffffffffffffffffffffffffffff8151168252600060208201516040602085015261423b6040850182613f2c565b949350505050565b602081526000612ad26020830184614206565b602081526000612ad260208301846140d6565b6000806040838503121561427c57600080fd5b614285836141d2565b946020939093013593505050565b6040815260006142a66040830185613f2c565b82810360208401526141478185613f2c565b600063ffffffff808351168452602081818501511681860152816040850151166040860152606084015160608601526080840151608086015260a0840151915060e060a086015261430c60e0860183614010565b60c08581015187830391880191909152805180835290830193506000918301905b8083101561434d578451825293830193600192909201919083019061432d565b509695505050505050565b602081526000612ad260208301846142b8565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143ce858351614206565b94509285019290850190600101614394565b600080600080604085870312156143f657600080fd5b843567ffffffffffffffff8082111561440e57600080fd5b61441a88838901613f89565b9096509450602087013591508082111561443357600080fd5b5061444087828801613f89565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e0602085015261449a60e0850182613f2c565b9050604083015184820360408601526144b38282613f2c565b9150506060830151600481106144cb576144cb61444c565b60608501526080830151600281106144e5576144e561444c565b8060808601525060a083015161451360a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161452760c086018215159052565b509392505050565b602081526000612ad2602083018461447b565b8015158114612abb57600080fd5b803560ff811681146141e657600080fd5b60008060008060008060008060c0898b03121561457d57600080fd5b614586896141d2565b9750602089013567ffffffffffffffff808211156145a357600080fd5b6145af8c838d01613f89565b909950975060408b01359150808211156145c857600080fd5b506145d58b828c01613f89565b90965094505060608901356145e981614542565b925060808901356145f981614542565b915061460760a08a01614550565b90509295985092959890939650565b600080600080600080600060a0888a03121561463157600080fd5b873567ffffffffffffffff8082111561464957600080fd5b6146558b838c01613f89565b909950975060208a013591508082111561466e57600080fd5b5061467b8a828b01613f89565b909650945050604088013561468f81614542565b9250606088013561469f81614542565b91506146ad60808901614550565b905092959891949750929550565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261471e85835161447b565b945092850192908501906001016146e4565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526147938583516142b8565b94509285019290850190600101614759565b803573ffffffffffffffffffffffffffffffffffffffff811681146141e657600080fd5b6000602082840312156147db57600080fd5b612ad2826147a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156107f2576107f2614813565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361489057614890614813565b5060010190565b600181811c908216806148ab57607f821691505b6020821081036148e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff80831681810361490357614903614813565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261494157600080fd5b9190910192915050565b60006040823603121561495d57600080fd5b6040516040810167ffffffffffffffff828210818311171561498157614981613d25565b8160405261498e856147a5565b835260208501359150808211156149a457600080fd5b506149b136828601613e35565b60208301525092915050565b601f821115610697576000816000526020600020601f850160051c810160208610156149e65750805b601f850160051c820191505b818110156124d7578281556001016149f2565b815167ffffffffffffffff811115614a1f57614a1f613d25565b614a3381614a2d8454614897565b846149bd565b602080601f831160018114614a865760008415614a505750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556124d7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614ad357888601518255948401946001909101908401614ab4565b5085821015614b0f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614b3157600080fd5b815167ffffffffffffffff811115614b4857600080fd5b8201601f81018413614b5957600080fd5b8051614b67613e5482613def565b818152856020838501011115614b7c57600080fd5b614147826020830160208601613f08565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261494157600080fd5b600060808236031215614bd357600080fd5b614bdb613d54565b614be4836141d2565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff80821115614c1557600080fd5b9085019036601f830112614c2857600080fd5b813581811115614c3a57614c3a613d25565b8060051b9150614c4b848301613da0565b8181529183018401918481019036841115614c6557600080fd5b938501935b83851015614c8357843582529385019390850190614c6a565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614ccc57835183529284019291840191600101614cb0565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261494157600080fd5b8035600281106141e657600080fd5b600060a08236031215614d2d57600080fd5b614d35613d7d565b823567ffffffffffffffff80821115614d4d57600080fd5b614d5936838701613e35565b83526020850135915080821115614d6f57600080fd5b50614d7c36828601613e35565b602083015250604083013560048110614d9457600080fd5b6040820152614da560608401614d0c565b6060820152614db6608084016147a5565b608082015292915050565b6000602080835260008454614dd581614897565b8060208701526040600180841660008114614df75760018114614e3157614e61565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614e61565b89600052602060002060005b85811015614e585781548b8201860152908301908801614e3d565b8a016040019650505b509398975050505050505050565b600060208284031215614e8157600080fd5b8151612ad281614542565b60ff818116838216019081111561047457610474614813565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614eda57600080fd5b83018035915067ffffffffffffffff821115614ef557600080fd5b60200191503681900382131561104157600080fd5b67ffffffffffffffff831115614f2257614f22613d25565b614f3683614f308354614897565b836149bd565b6000601f841160018114614f885760008515614f525750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561501e565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614fd75786850135825560209485019460019092019101614fb7565b5086821015615012577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8181038181111561047457610474614813565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156150a057600080fd5b8560051b808860a0850137820182810360a090810160208501526150c690820187613f2c565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", +} + +var CapabilitiesRegistryABI = CapabilitiesRegistryMetaData.ABI + +var CapabilitiesRegistryBin = CapabilitiesRegistryMetaData.Bin + +func DeployCapabilitiesRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CapabilitiesRegistry, error) { + parsed, err := CapabilitiesRegistryMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CapabilitiesRegistryBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CapabilitiesRegistry{address: address, abi: *parsed, CapabilitiesRegistryCaller: CapabilitiesRegistryCaller{contract: contract}, CapabilitiesRegistryTransactor: CapabilitiesRegistryTransactor{contract: contract}, CapabilitiesRegistryFilterer: CapabilitiesRegistryFilterer{contract: contract}}, nil +} + +type CapabilitiesRegistry struct { + address common.Address + abi abi.ABI + CapabilitiesRegistryCaller + CapabilitiesRegistryTransactor + CapabilitiesRegistryFilterer +} + +type CapabilitiesRegistryCaller struct { + contract *bind.BoundContract +} + +type CapabilitiesRegistryTransactor struct { + contract *bind.BoundContract +} + +type CapabilitiesRegistryFilterer struct { + contract *bind.BoundContract +} + +type CapabilitiesRegistrySession struct { + Contract *CapabilitiesRegistry + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CapabilitiesRegistryCallerSession struct { + Contract *CapabilitiesRegistryCaller + CallOpts bind.CallOpts +} + +type CapabilitiesRegistryTransactorSession struct { + Contract *CapabilitiesRegistryTransactor + TransactOpts bind.TransactOpts +} + +type CapabilitiesRegistryRaw struct { + Contract *CapabilitiesRegistry +} + +type CapabilitiesRegistryCallerRaw struct { + Contract *CapabilitiesRegistryCaller +} + +type CapabilitiesRegistryTransactorRaw struct { + Contract *CapabilitiesRegistryTransactor +} + +func NewCapabilitiesRegistry(address common.Address, backend bind.ContractBackend) (*CapabilitiesRegistry, error) { + abi, err := abi.JSON(strings.NewReader(CapabilitiesRegistryABI)) + if err != nil { + return nil, err + } + contract, err := bindCapabilitiesRegistry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CapabilitiesRegistry{address: address, abi: abi, CapabilitiesRegistryCaller: CapabilitiesRegistryCaller{contract: contract}, CapabilitiesRegistryTransactor: CapabilitiesRegistryTransactor{contract: contract}, CapabilitiesRegistryFilterer: CapabilitiesRegistryFilterer{contract: contract}}, nil +} + +func NewCapabilitiesRegistryCaller(address common.Address, caller bind.ContractCaller) (*CapabilitiesRegistryCaller, error) { + contract, err := bindCapabilitiesRegistry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryCaller{contract: contract}, nil +} + +func NewCapabilitiesRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*CapabilitiesRegistryTransactor, error) { + contract, err := bindCapabilitiesRegistry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryTransactor{contract: contract}, nil +} + +func NewCapabilitiesRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*CapabilitiesRegistryFilterer, error) { + contract, err := bindCapabilitiesRegistry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryFilterer{contract: contract}, nil +} + +func bindCapabilitiesRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CapabilitiesRegistryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CapabilitiesRegistry.Contract.CapabilitiesRegistryCaller.contract.Call(opts, result, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.CapabilitiesRegistryTransactor.contract.Transfer(opts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.CapabilitiesRegistryTransactor.contract.Transact(opts, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CapabilitiesRegistry.Contract.contract.Call(opts, result, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.contract.Transfer(opts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.contract.Transact(opts, method, params...) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([]CapabilitiesRegistryCapabilityInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapabilities") + + if err != nil { + return *new([]CapabilitiesRegistryCapabilityInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryCapabilityInfo)).(*[]CapabilitiesRegistryCapabilityInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapabilities() ([]CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapabilities(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapabilities() ([]CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapabilities(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapability", hashedId) + + if err != nil { + return *new(CapabilitiesRegistryCapabilityInfo), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryCapabilityInfo)).(*CapabilitiesRegistryCapabilityInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapability(hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapability(&_CapabilitiesRegistry.CallOpts, hashedId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapability(hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { + return _CapabilitiesRegistry.Contract.GetCapability(&_CapabilitiesRegistry.CallOpts, hashedId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapabilityConfigs", donId, capabilityId) + + if err != nil { + return *new([]byte), *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) + + return out0, out1, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { + return _CapabilitiesRegistry.Contract.GetCapabilityConfigs(&_CapabilitiesRegistry.CallOpts, donId, capabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { + return _CapabilitiesRegistry.Contract.GetCapabilityConfigs(&_CapabilitiesRegistry.CallOpts, donId, capabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetDON(opts *bind.CallOpts, donId uint32) (CapabilitiesRegistryDONInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getDON", donId) + + if err != nil { + return *new(CapabilitiesRegistryDONInfo), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryDONInfo)).(*CapabilitiesRegistryDONInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetDON(donId uint32) (CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDON(&_CapabilitiesRegistry.CallOpts, donId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetDON(donId uint32) (CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDON(&_CapabilitiesRegistry.CallOpts, donId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetDONs(opts *bind.CallOpts) ([]CapabilitiesRegistryDONInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getDONs") + + if err != nil { + return *new([]CapabilitiesRegistryDONInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryDONInfo)).(*[]CapabilitiesRegistryDONInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetDONs() ([]CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDONs(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetDONs() ([]CapabilitiesRegistryDONInfo, error) { + return _CapabilitiesRegistry.Contract.GetDONs(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getHashedCapabilityId", labelledName, version) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { + return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { + return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNode", p2pId) + + if err != nil { + return *new(CapabilitiesRegistryNodeInfo), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryNodeInfo)).(*CapabilitiesRegistryNodeInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNode(p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNode(p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) + + if err != nil { + return *new(CapabilitiesRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryNodeOperator)).(*CapabilitiesRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodeOperator(nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperator(&_CapabilitiesRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperator(nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperator(&_CapabilitiesRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodeOperators(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodeOperators") + + if err != nil { + return *new([]CapabilitiesRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryNodeOperator)).(*[]CapabilitiesRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodeOperators() ([]CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperators() ([]CapabilitiesRegistryNodeOperator, error) { + return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodes(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeInfo, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodes") + + if err != nil { + return *new([]CapabilitiesRegistryNodeInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryNodeInfo)).(*[]CapabilitiesRegistryNodeInfo) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodes() ([]CapabilitiesRegistryNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodes() ([]CapabilitiesRegistryNodeInfo, error) { + return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", hashedCapabilityId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilitiesRegistry.Contract.IsCapabilityDeprecated(&_CapabilitiesRegistry.CallOpts, hashedCapabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilitiesRegistry.Contract.IsCapabilityDeprecated(&_CapabilitiesRegistry.CallOpts, hashedCapabilityId) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) Owner() (common.Address, error) { + return _CapabilitiesRegistry.Contract.Owner(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) Owner() (common.Address, error) { + return _CapabilitiesRegistry.Contract.Owner(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CapabilitiesRegistry.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) TypeAndVersion() (string, error) { + return _CapabilitiesRegistry.Contract.TypeAndVersion(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) TypeAndVersion() (string, error) { + return _CapabilitiesRegistry.Contract.TypeAndVersion(&_CapabilitiesRegistry.CallOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "acceptOwnership") +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AcceptOwnership() (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AcceptOwnership(&_CapabilitiesRegistry.TransactOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AcceptOwnership(&_CapabilitiesRegistry.TransactOpts) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addCapabilities", capabilities) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddCapabilities(capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddCapabilities(&_CapabilitiesRegistry.TransactOpts, capabilities) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddCapabilities(capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddCapabilities(&_CapabilitiesRegistry.TransactOpts, capabilities) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addDON", nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddDON(&_CapabilitiesRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddDON(&_CapabilitiesRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddNodeOperators(nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "addNodes", nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.AddNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "deprecateCapabilities", hashedCapabilityIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.DeprecateCapabilities(&_CapabilitiesRegistry.TransactOpts, hashedCapabilityIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.DeprecateCapabilities(&_CapabilitiesRegistry.TransactOpts, hashedCapabilityIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "removeDONs", donIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveDONs(&_CapabilitiesRegistry.TransactOpts, donIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveDONs(&_CapabilitiesRegistry.TransactOpts, donIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "removeNodes", removedNodeP2PIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodes(&_CapabilitiesRegistry.TransactOpts, removedNodeP2PIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.RemoveNodes(&_CapabilitiesRegistry.TransactOpts, removedNodeP2PIds) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "transferOwnership", to) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.TransferOwnership(&_CapabilitiesRegistry.TransactOpts, to) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.TransferOwnership(&_CapabilitiesRegistry.TransactOpts, to) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "updateDON", donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateDON(&_CapabilitiesRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateDON(&_CapabilitiesRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "updateNodeOperators", nodeOperatorIds, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds, nodeOperators) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.contract.Transact(opts, "updateNodes", nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { + return _CapabilitiesRegistry.Contract.UpdateNodes(&_CapabilitiesRegistry.TransactOpts, nodes) +} + +type CapabilitiesRegistryCapabilityConfiguredIterator struct { + Event *CapabilitiesRegistryCapabilityConfigured + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryCapabilityConfigured) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryCapabilityConfigured) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryCapabilityConfigured struct { + HashedCapabilityId [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityConfiguredIterator, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryCapabilityConfiguredIterator{contract: _CapabilitiesRegistry.contract, event: "CapabilityConfigured", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryCapabilityConfigured) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseCapabilityConfigured(log types.Log) (*CapabilitiesRegistryCapabilityConfigured, error) { + event := new(CapabilitiesRegistryCapabilityConfigured) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryCapabilityDeprecatedIterator struct { + Event *CapabilitiesRegistryCapabilityDeprecated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryCapabilityDeprecated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryCapabilityDeprecated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryCapabilityDeprecated struct { + HashedCapabilityId [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityDeprecatedIterator, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryCapabilityDeprecatedIterator{contract: _CapabilitiesRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) { + + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryCapabilityDeprecated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) { + event := new(CapabilitiesRegistryCapabilityDeprecated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryConfigSetIterator struct { + Event *CapabilitiesRegistryConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryConfigSetIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryConfigSet struct { + DonId uint32 + ConfigCount uint32 + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterConfigSet(opts *bind.FilterOpts) (*CapabilitiesRegistryConfigSetIterator, error) { + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &CapabilitiesRegistryConfigSetIterator{contract: _CapabilitiesRegistry.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet) (event.Subscription, error) { + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryConfigSet) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) { + event := new(CapabilitiesRegistryConfigSet) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeAddedIterator struct { + Event *CapabilitiesRegistryNodeAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryNodeAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeAdded struct { + P2pId [32]byte + NodeOperatorId uint32 + Signer [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeAddedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeAdded", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeAddedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeAdded", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeAdded(log types.Log) (*CapabilitiesRegistryNodeAdded, error) { + event := new(CapabilitiesRegistryNodeAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeOperatorAddedIterator struct { + Event *CapabilitiesRegistryNodeOperatorAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeOperatorAdded struct { + NodeOperatorId uint32 + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorAddedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeOperatorAddedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeOperatorAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorAdded(log types.Log) (*CapabilitiesRegistryNodeOperatorAdded, error) { + event := new(CapabilitiesRegistryNodeOperatorAdded) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeOperatorRemovedIterator struct { + Event *CapabilitiesRegistryNodeOperatorRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeOperatorRemoved struct { + NodeOperatorId uint32 + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeOperatorRemovedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeOperatorRemovedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeOperatorRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorRemoved(log types.Log) (*CapabilitiesRegistryNodeOperatorRemoved, error) { + event := new(CapabilitiesRegistryNodeOperatorRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeOperatorUpdatedIterator struct { + Event *CapabilitiesRegistryNodeOperatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeOperatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeOperatorUpdated struct { + NodeOperatorId uint32 + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorUpdatedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeOperatorUpdatedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeOperatorUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorUpdated(log types.Log) (*CapabilitiesRegistryNodeOperatorUpdated, error) { + event := new(CapabilitiesRegistryNodeOperatorUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeRemovedIterator struct { + Event *CapabilitiesRegistryNodeRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryNodeRemovedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeRemoved struct { + P2pId [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilitiesRegistryNodeRemovedIterator, error) { + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeRemoved") + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeRemovedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeRemoved", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeRemoved) (event.Subscription, error) { + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeRemoved(log types.Log) (*CapabilitiesRegistryNodeRemoved, error) { + event := new(CapabilitiesRegistryNodeRemoved) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryNodeUpdatedIterator struct { + Event *CapabilitiesRegistryNodeUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryNodeUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryNodeUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryNodeUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryNodeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryNodeUpdated struct { + P2pId [32]byte + NodeOperatorId uint32 + Signer [32]byte + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeUpdatedIterator, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeUpdated", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryNodeUpdatedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) { + + var nodeOperatorIdRule []interface{} + for _, nodeOperatorIdItem := range nodeOperatorId { + nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeUpdated", nodeOperatorIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryNodeUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeUpdated(log types.Log) (*CapabilitiesRegistryNodeUpdated, error) { + event := new(CapabilitiesRegistryNodeUpdated) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryOwnershipTransferRequestedIterator struct { + Event *CapabilitiesRegistryOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryOwnershipTransferRequestedIterator{contract: _CapabilitiesRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryOwnershipTransferRequested) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*CapabilitiesRegistryOwnershipTransferRequested, error) { + event := new(CapabilitiesRegistryOwnershipTransferRequested) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilitiesRegistryOwnershipTransferredIterator struct { + Event *CapabilitiesRegistryOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilitiesRegistryOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilitiesRegistryOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilitiesRegistryOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CapabilitiesRegistryOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilitiesRegistryOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CapabilitiesRegistryOwnershipTransferredIterator{contract: _CapabilitiesRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilitiesRegistryOwnershipTransferred) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*CapabilitiesRegistryOwnershipTransferred, error) { + event := new(CapabilitiesRegistryOwnershipTransferred) + if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CapabilitiesRegistry *CapabilitiesRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CapabilitiesRegistry.abi.Events["CapabilityConfigured"].ID: + return _CapabilitiesRegistry.ParseCapabilityConfigured(log) + case _CapabilitiesRegistry.abi.Events["CapabilityDeprecated"].ID: + return _CapabilitiesRegistry.ParseCapabilityDeprecated(log) + case _CapabilitiesRegistry.abi.Events["ConfigSet"].ID: + return _CapabilitiesRegistry.ParseConfigSet(log) + case _CapabilitiesRegistry.abi.Events["NodeAdded"].ID: + return _CapabilitiesRegistry.ParseNodeAdded(log) + case _CapabilitiesRegistry.abi.Events["NodeOperatorAdded"].ID: + return _CapabilitiesRegistry.ParseNodeOperatorAdded(log) + case _CapabilitiesRegistry.abi.Events["NodeOperatorRemoved"].ID: + return _CapabilitiesRegistry.ParseNodeOperatorRemoved(log) + case _CapabilitiesRegistry.abi.Events["NodeOperatorUpdated"].ID: + return _CapabilitiesRegistry.ParseNodeOperatorUpdated(log) + case _CapabilitiesRegistry.abi.Events["NodeRemoved"].ID: + return _CapabilitiesRegistry.ParseNodeRemoved(log) + case _CapabilitiesRegistry.abi.Events["NodeUpdated"].ID: + return _CapabilitiesRegistry.ParseNodeUpdated(log) + case _CapabilitiesRegistry.abi.Events["OwnershipTransferRequested"].ID: + return _CapabilitiesRegistry.ParseOwnershipTransferRequested(log) + case _CapabilitiesRegistry.abi.Events["OwnershipTransferred"].ID: + return _CapabilitiesRegistry.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CapabilitiesRegistryCapabilityConfigured) Topic() common.Hash { + return common.HexToHash("0x04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae") +} + +func (CapabilitiesRegistryCapabilityDeprecated) Topic() common.Hash { + return common.HexToHash("0xdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21") +} + +func (CapabilitiesRegistryConfigSet) Topic() common.Hash { + return common.HexToHash("0xf264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651") +} + +func (CapabilitiesRegistryNodeAdded) Topic() common.Hash { + return common.HexToHash("0x74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05") +} + +func (CapabilitiesRegistryNodeOperatorAdded) Topic() common.Hash { + return common.HexToHash("0x78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e") +} + +func (CapabilitiesRegistryNodeOperatorRemoved) Topic() common.Hash { + return common.HexToHash("0xa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a") +} + +func (CapabilitiesRegistryNodeOperatorUpdated) Topic() common.Hash { + return common.HexToHash("0x86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28") +} + +func (CapabilitiesRegistryNodeRemoved) Topic() common.Hash { + return common.HexToHash("0x5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb9753205") +} + +func (CapabilitiesRegistryNodeUpdated) Topic() common.Hash { + return common.HexToHash("0x4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b") +} + +func (CapabilitiesRegistryOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CapabilitiesRegistryOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CapabilitiesRegistry *CapabilitiesRegistry) Address() common.Address { + return _CapabilitiesRegistry.address +} + +type CapabilitiesRegistryInterface interface { + GetCapabilities(opts *bind.CallOpts) ([]CapabilitiesRegistryCapabilityInfo, error) + + GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) + + GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) + + GetDON(opts *bind.CallOpts, donId uint32) (CapabilitiesRegistryDONInfo, error) + + GetDONs(opts *bind.CallOpts) ([]CapabilitiesRegistryDONInfo, error) + + GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) + + GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilitiesRegistryNodeInfo, error) + + GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) + + GetNodeOperators(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeOperator, error) + + GetNodes(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeInfo, error) + + IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) + + AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) + + AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) + + AddNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) + + DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) + + RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) + + RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) + + RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) + + UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) + + UpdateNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) + + FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityConfiguredIterator, error) + + WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) + + ParseCapabilityConfigured(log types.Log) (*CapabilitiesRegistryCapabilityConfigured, error) + + FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityDeprecatedIterator, error) + + WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) + + ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) + + FilterConfigSet(opts *bind.FilterOpts) (*CapabilitiesRegistryConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) + + FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeAddedIterator, error) + + WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) + + ParseNodeAdded(log types.Log) (*CapabilitiesRegistryNodeAdded, error) + + FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorAddedIterator, error) + + WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorAdded(log types.Log) (*CapabilitiesRegistryNodeOperatorAdded, error) + + FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeOperatorRemovedIterator, error) + + WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) + + ParseNodeOperatorRemoved(log types.Log) (*CapabilitiesRegistryNodeOperatorRemoved, error) + + FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorUpdatedIterator, error) + + WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorUpdated(log types.Log) (*CapabilitiesRegistryNodeOperatorUpdated, error) + + FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilitiesRegistryNodeRemovedIterator, error) + + WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeRemoved) (event.Subscription, error) + + ParseNodeRemoved(log types.Log) (*CapabilitiesRegistryNodeRemoved, error) + + FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeUpdatedIterator, error) + + WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) + + ParseNodeUpdated(log types.Log) (*CapabilitiesRegistryNodeUpdated, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CapabilitiesRegistryOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CapabilitiesRegistryOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generated/forwarder/forwarder.go b/core/gethwrappers/keystone/generated/forwarder/forwarder.go index b4f209f1c3..0412241cf7 100644 --- a/core/gethwrappers/keystone/generated/forwarder/forwarder.go +++ b/core/gethwrappers/keystone/generated/forwarder/forwarder.go @@ -31,8 +31,8 @@ var ( ) var KeystoneForwarderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"AlreadyProcessed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"InvalidSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"InvalidVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"ReportProcessed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"clearConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiverAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportContext\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"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\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611786806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146101cb578063ee59d26c146101e9578063ef6e17a0146101fc578063f2fde38b1461020f57600080fd5b8063112895651461008d578063181f5a77146100a257806379ba5097146100ea5780638864b864146100f2575b600080fd5b6100a061009b3660046112e6565b610222565b005b604080518082018252601781527f4b657973746f6e65466f7277617264657220312e302e30000000000000000000602082015290516100e191906113f5565b60405180910390f35b6100a0610983565b6101a661010036600461140f565b6040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348501939093527fffff000000000000000000000000000000000000000000000000000000000000919091166054840152805160368185030181526056909301815282519282019290922060009081526003909152205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e1565b60005473ffffffffffffffffffffffffffffffffffffffff166101a6565b6100a06101f7366004611488565b610a80565b6100a061020a366004611506565b610de5565b6100a061021d366004611539565b610ee5565b60015474010000000000000000000000000000000000000000900460ff1615610277576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055606d8510156102f1576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008060006103388b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ef992505050565b6040805163ffffffff808616602083015284169181019190915293985096509093509150606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120600081815260029093529082205490945060ff16908190036103f8576040517f16c0791600000000000000000000000000000000000000000000000000000000815263ffffffff8085166004830152831660248201526044015b60405180910390fd5b86610404826001611583565b60ff161461045657610417816001611583565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018890526044016103ef565b50506040805160608d901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603482018790527fffff0000000000000000000000000000000000000000000000000000000000008616605483015282516036818403018152605690920190925280519101206000915060008181526003602052604090205490915073ffffffffffffffffffffffffffffffffffffffff1615610538576040517f1a20d3e6000000000000000000000000000000000000000000000000000000008152600481018290526024016103ef565b60008a8a60405161054a9291906115a2565b604051908190038120610563918b908b906020016115b2565b604051602081830303815290604052805190602001209050610583611173565b6000805b888110156107ea5760008060006105f58d8d868181106105a9576105a96115cc565b90506020028101906105bb91906115fb565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f9b92505050565b91945092509050600060018861060c84601b611583565b6040805160008152602081018083529390935260ff90911690820152606081018690526080810185905260a0016020604051602081039080840390855afa15801561065b573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015160008d81526002602081815284832073ffffffffffffffffffffffffffffffffffffffff851684529091019052918220549850925060ff88169003905061070f576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016103ef565b61071a600187611660565b955060008760ff8816601f8110610733576107336115cc565b602002015173ffffffffffffffffffffffffffffffffffffffff161461079d576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016103ef565b80878760ff16601f81106107b3576107b36115cc565b73ffffffffffffffffffffffffffffffffffffffff9092166020929092020152506107e392508391506116799050565b9050610587565b5050505060008b73ffffffffffffffffffffffffffffffffffffffff1663805f21328c8c602d90606d92610820939291906116b1565b8e8e606d908092610833939291906116b1565b6040518563ffffffff1660e01b81526004016108529493929190611724565b600060405180830381600087803b15801561086c57600080fd5b505af192505050801561087d575060015b15610886575060015b604080518082018252338152821515602080830191825260008681526003909152839020915182549151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9182161791909117909155905186918e16907fbe015fd2fd7c1a00158e111095c794ae7030eb413d2a0990e5b78d3114df1d499061094590851515815260200190565b60405180910390a35050600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16905550505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016103ef565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a88610ffb565b8260ff16600003610ac5576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f811115610b0a576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f60248201526044016103ef565b610b15836003611756565b60ff168111610b735780610b2a846003611756565b610b35906001611583565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff1660248201526044016103ef565b6040805163ffffffff878116602080840191909152908716828401528251808303840181526060909201909252805191012060005b600082815260026020526040902060010154811015610c32576000828152600260205260408120600101805483908110610be457610be46115cc565b60009182526020808320909101548583526002808352604080852073ffffffffffffffffffffffffffffffffffffffff9093168552910190915281205550610c2b81611679565b9050610ba8565b506000818152600260205260409020610c4f906001018484611192565b5060005b82811015610d9f576000848483818110610c6f57610c6f6115cc565b9050602002016020810190610c849190611539565b600084815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205490915015610d08576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016103ef565b610d13826001611583565b600084815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff909616808552868401835290842060ff959095169094559081526001938401805494850181558252902090910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055610d9881611679565b9050610c53565b50600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff949094169390931790925550505050565b610ded610ffb565b6040805163ffffffff848116602080840191909152908416828401528251808303840181526060909201909252805191012060005b600082815260026020526040902060010154811015610eac576000828152600260205260408120600101805483908110610e5e57610e5e6115cc565b60009182526020808320909101548583526002808352604080852073ffffffffffffffffffffffffffffffffffffffff9093168552910190915281205550610ea581611679565b9050610e22565b50600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050565b610eed610ffb565b610ef68161107e565b50565b60008060008084600081518110610f1257610f126115cc565b60209101015160f81c600114610f735784600081518110610f3557610f356115cc565b01602001516040517f7207be2000000000000000000000000000000000000000000000000000000000815260f89190911c60048201526024016103ef565b50505050602181015160458201516049830151608b90930151919360e091821c9390911c9190565b60008060006041845114610fdd57836040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016103ef91906113f5565b50505060208101516040820151606090920151909260009190911a90565b60005473ffffffffffffffffffffffffffffffffffffffff16331461107c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ef565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ef565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b604051806103e00160405280601f906020820280368337509192915050565b82805482825590600052602060002090810192821561120a579160200282015b8281111561120a5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906111b2565b5061121692915061121a565b5090565b5b80821115611216576000815560010161121b565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125357600080fd5b919050565b60008083601f84011261126a57600080fd5b50813567ffffffffffffffff81111561128257600080fd5b60208301915083602082850101111561129a57600080fd5b9250929050565b60008083601f8401126112b357600080fd5b50813567ffffffffffffffff8111156112cb57600080fd5b6020830191508360208260051b850101111561129a57600080fd5b60008060008060008060006080888a03121561130157600080fd5b61130a8861122f565b9650602088013567ffffffffffffffff8082111561132757600080fd5b6113338b838c01611258565b909850965060408a013591508082111561134c57600080fd5b6113588b838c01611258565b909650945060608a013591508082111561137157600080fd5b5061137e8a828b016112a1565b989b979a50959850939692959293505050565b6000815180845260005b818110156113b75760208185018101518683018201520161139b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006114086020830184611391565b9392505050565b60008060006060848603121561142457600080fd5b61142d8461122f565b92506020840135915060408401357fffff0000000000000000000000000000000000000000000000000000000000008116811461146957600080fd5b809150509250925092565b803563ffffffff8116811461125357600080fd5b6000806000806000608086880312156114a057600080fd5b6114a986611474565b94506114b760208701611474565b9350604086013560ff811681146114cd57600080fd5b9250606086013567ffffffffffffffff8111156114e957600080fd5b6114f5888289016112a1565b969995985093965092949392505050565b6000806040838503121561151957600080fd5b61152283611474565b915061153060208401611474565b90509250929050565b60006020828403121561154b57600080fd5b6114088261122f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216019081111561159c5761159c611554565b92915050565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261163057600080fd5b83018035915067ffffffffffffffff82111561164b57600080fd5b60200191503681900382131561129a57600080fd5b60ff828116828216039081111561159c5761159c611554565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116aa576116aa611554565b5060010190565b600080858511156116c157600080fd5b838611156116ce57600080fd5b5050820193919092039150565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006117386040830186886116db565b828103602084015261174b8185876116db565b979650505050505050565b60ff818116838216029081169081811461177257611772611554565b509291505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"configId\",\"type\":\"uint64\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"InvalidSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedForwarder\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderRemoved\",\"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\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"ReportProcessed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"addForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"clearConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionState\",\"outputs\":[{\"internalType\":\"enumIRouter.TransmissionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"removeForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportContext\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"validatedReport\",\"type\":\"bytes\"}],\"name\":\"route\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"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\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b038481169190911790915581161561009757610097816100b9565b5050306000908152600360205260409020805460ff1916600117905550610162565b336001600160a01b038216036101115760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611b2d80620001726000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806379ba50971161008c578063abcef55411610066578063abcef5541461023e578063ee59d26c14610277578063ef6e17a01461028a578063f2fde38b1461029d57600080fd5b806379ba5097146101e05780638864b864146101e85780638da5cb5b1461022057600080fd5b8063354bdd66116100c8578063354bdd661461017957806343c164671461019a5780634d93172d146101ba5780635c41d2fe146101cd57600080fd5b806311289565146100ef578063181f5a7714610104578063233fd52d14610156575b600080fd5b6101026100fd366004611474565b6102b0565b005b6101406040518060400160405280601a81526020017f466f7277617264657220616e6420526f7574657220312e302e3000000000000081525081565b60405161014d919061151f565b60405180910390f35b61016961016436600461158c565b61080d565b604051901515815260200161014d565b61018c610187366004611614565b610a00565b60405190815260200161014d565b6101ad6101a8366004611614565b610a84565b60405161014d9190611679565b6101026101c83660046116ba565b610b09565b6101026101db3660046116ba565b610b85565b610102610c04565b6101fb6101f6366004611614565b610d01565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014d565b60005473ffffffffffffffffffffffffffffffffffffffff166101fb565b61016961024c3660046116ba565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6101026102853660046116e9565b610d41565b610102610298366004611767565b6110ba565b6101026102ab3660046116ba565b61115a565b606d8510156102eb576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061032f89898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061116e92505050565b67ffffffffffffffff8216600090815260026020526040812080549497509195509193509160ff16908190036103a2576040517fdf3b81ea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b856103ae8260016117c9565b60ff1614610400576103c18160016117c9565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101879052604401610399565b60008b8b6040516104129291906117e8565b60405190819003812061042b918c908c906020016117f8565b60405160208183030381529060405280519060200120905061044b611301565b60005b888110156106cd573660008b8b8481811061046b5761046b611812565b905060200281019061047d9190611841565b9092509050604181146104c05781816040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016103999291906118ef565b6000600186848460408181106104d8576104d8611812565b6104ea92013560f81c9050601b6117c9565b6104f860206000878961190b565b61050191611935565b61050f60406020888a61190b565b61051891611935565b6040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610566573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8116600090815260028c0160205291822054909350915081900361060c576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610399565b600086826020811061062057610620611812565b602002015173ffffffffffffffffffffffffffffffffffffffff161461068a576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610399565b8186826020811061069d5761069d611812565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015250506001909201915061044e9050565b50505050505060003073ffffffffffffffffffffffffffffffffffffffff1663233fd52d6106fc8c8686610a00565b338d8d8d602d90606d926107129392919061190b565b8f8f606d9080926107259392919061190b565b6040518863ffffffff1660e01b81526004016107479796959493929190611971565b6020604051808303816000875af1158015610766573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061078a91906119d2565b9050817dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916838b73ffffffffffffffffffffffffffffffffffffffff167f3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b5846040516107f9911515815260200190565b60405180910390a450505050505050505050565b3360009081526003602052604081205460ff16610856576040517fd79e123d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008881526004602052604090205473ffffffffffffffffffffffffffffffffffffffff16156108b5576040517fa53dc8ca00000000000000000000000000000000000000000000000000000000815260048101899052602401610399565b600088815260046020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a81169190911790915587163b9003610917575060006109f5565b6040517f805f213200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169063805f21329061096f9088908890889088906004016119f4565b600060405180830381600087803b15801561098957600080fd5b505af192505050801561099a575060015b6109a6575060006109f5565b50600087815260046020526040902080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560015b979650505050505050565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090505b9392505050565b600080610a92858585610a00565b60008181526004602052604090205490915073ffffffffffffffffffffffffffffffffffffffff16610ac8576000915050610a7d565b60008181526004602052604090205474010000000000000000000000000000000000000000900460ff16610afd576002610b00565b60015b95945050505050565b610b11611189565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d389190a250565b610b8d611189565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e79190a250565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610399565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600060046000610d12868686610a00565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff16949350505050565b610d49611189565b8260ff16600003610d86576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f811115610dcb576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f6024820152604401610399565b610dd6836003611a1b565b60ff168111610e345780610deb846003611a1b565b610df69060016117c9565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff166024820152604401610399565b67ffffffff00000000602086901b1663ffffffff85161760005b67ffffffffffffffff8216600090815260026020526040902060010154811015610ee45767ffffffffffffffff8216600090815260026020819052604082206001810180549190920192919084908110610eaa57610eaa611812565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812055600101610e4e565b5060005b82811015610ffc576000848483818110610f0457610f04611812565b9050602002016020810190610f1991906116ba565b67ffffffffffffffff8416600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205490915015610fa8576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610399565b610fb3826001611a3e565b67ffffffffffffffff8416600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff90961684529490910190529190912055600101610ee8565b5067ffffffffffffffff81166000908152600260205260409020611024906001018484611320565b5067ffffffffffffffff81166000908152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff87161790555163ffffffff86811691908816907f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455906110aa90889088908890611a51565b60405180910390a3505050505050565b6110c2611189565b63ffffffff818116602084811b67ffffffff00000000168217600090815260028252604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051828152928301905291928516917f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a4559160405161114e929190611ab7565b60405180910390a35050565b611162611189565b61116b8161120c565b50565b60218101516045820151608b90920151909260c09290921c91565b60005473ffffffffffffffffffffffffffffffffffffffff16331461120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610399565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361128b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610399565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518061040001604052806020906020820280368337509192915050565b828054828255906000526020600020908101928215611398579160200282015b828111156113985781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190611340565b506113a49291506113a8565b5090565b5b808211156113a457600081556001016113a9565b803573ffffffffffffffffffffffffffffffffffffffff811681146113e157600080fd5b919050565b60008083601f8401126113f857600080fd5b50813567ffffffffffffffff81111561141057600080fd5b60208301915083602082850101111561142857600080fd5b9250929050565b60008083601f84011261144157600080fd5b50813567ffffffffffffffff81111561145957600080fd5b6020830191508360208260051b850101111561142857600080fd5b60008060008060008060006080888a03121561148f57600080fd5b611498886113bd565b9650602088013567ffffffffffffffff808211156114b557600080fd5b6114c18b838c016113e6565b909850965060408a01359150808211156114da57600080fd5b6114e68b838c016113e6565b909650945060608a01359150808211156114ff57600080fd5b5061150c8a828b0161142f565b989b979a50959850939692959293505050565b60006020808352835180602085015260005b8181101561154d57858101830151858201604001528201611531565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600080600080600080600060a0888a0312156115a757600080fd5b873596506115b7602089016113bd565b95506115c5604089016113bd565b9450606088013567ffffffffffffffff808211156115e257600080fd5b6115ee8b838c016113e6565b909650945060808a013591508082111561160757600080fd5b5061150c8a828b016113e6565b60008060006060848603121561162957600080fd5b611632846113bd565b92506020840135915060408401357fffff0000000000000000000000000000000000000000000000000000000000008116811461166e57600080fd5b809150509250925092565b60208101600383106116b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000602082840312156116cc57600080fd5b610a7d826113bd565b803563ffffffff811681146113e157600080fd5b60008060008060006080868803121561170157600080fd5b61170a866116d5565b9450611718602087016116d5565b9350604086013560ff8116811461172e57600080fd5b9250606086013567ffffffffffffffff81111561174a57600080fd5b6117568882890161142f565b969995985093965092949392505050565b6000806040838503121561177a57600080fd5b611783836116d5565b9150611791602084016116d5565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff81811683821601908111156117e2576117e261179a565b92915050565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261187657600080fd5b83018035915067ffffffffffffffff82111561189157600080fd5b60200191503681900382131561142857600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6020815260006119036020830184866118a6565b949350505050565b6000808585111561191b57600080fd5b8386111561192857600080fd5b5050820193919092039150565b803560208310156117e2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525060a060608301526119b160a0830186886118a6565b82810360808401526119c48185876118a6565b9a9950505050505050505050565b6000602082840312156119e457600080fd5b81518015158114610a7d57600080fd5b604081526000611a086040830186886118a6565b82810360208401526109f58185876118a6565b60ff8181168382160290811690818114611a3757611a3761179a565b5092915050565b808201808211156117e2576117e261179a565b60ff8416815260406020808301829052908201839052600090849060608401835b86811015611aab5773ffffffffffffffffffffffffffffffffffffffff611a98856113bd565b1682529282019290820190600101611a72565b50979650505050505050565b60006040820160ff8516835260206040602085015281855180845260608601915060208701935060005b81811015611b1357845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101611ae1565b509097965050505050505056fea164736f6c6343000818000a", } var KeystoneForwarderABI = KeystoneForwarderMetaData.ABI @@ -171,6 +171,50 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorRaw) Transact(opts *bind.Tr return _KeystoneForwarder.Contract.contract.Transact(opts, method, params...) } +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionId", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { + return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionState(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionState", receiver, workflowExecutionId, reportId) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionState(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) { + return _KeystoneForwarder.Contract.GetTransmissionState(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionState(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) { + return _KeystoneForwarder.Contract.GetTransmissionState(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) +} + func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { var out []interface{} err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmitter", receiver, workflowExecutionId, reportId) @@ -193,6 +237,28 @@ func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmitter(receive return _KeystoneForwarder.Contract.GetTransmitter(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) } +func (_KeystoneForwarder *KeystoneForwarderCaller) IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) { + var out []interface{} + err := _KeystoneForwarder.contract.Call(opts, &out, "isForwarder", forwarder) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_KeystoneForwarder *KeystoneForwarderSession) IsForwarder(forwarder common.Address) (bool, error) { + return _KeystoneForwarder.Contract.IsForwarder(&_KeystoneForwarder.CallOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderCallerSession) IsForwarder(forwarder common.Address) (bool, error) { + return _KeystoneForwarder.Contract.IsForwarder(&_KeystoneForwarder.CallOpts, forwarder) +} + func (_KeystoneForwarder *KeystoneForwarderCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _KeystoneForwarder.contract.Call(opts, &out, "owner") @@ -249,6 +315,18 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorSession) AcceptOwnership() return _KeystoneForwarder.Contract.AcceptOwnership(&_KeystoneForwarder.TransactOpts) } +func (_KeystoneForwarder *KeystoneForwarderTransactor) AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "addForwarder", forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.AddForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.AddForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + func (_KeystoneForwarder *KeystoneForwarderTransactor) ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) { return _KeystoneForwarder.contract.Transact(opts, "clearConfig", donId, configVersion) } @@ -261,16 +339,40 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorSession) ClearConfig(donId return _KeystoneForwarder.Contract.ClearConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion) } -func (_KeystoneForwarder *KeystoneForwarderTransactor) Report(opts *bind.TransactOpts, receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "report", receiverAddress, rawReport, reportContext, signatures) +func (_KeystoneForwarder *KeystoneForwarderTransactor) RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "removeForwarder", forwarder) } -func (_KeystoneForwarder *KeystoneForwarderSession) Report(receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiverAddress, rawReport, reportContext, signatures) +func (_KeystoneForwarder *KeystoneForwarderSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.RemoveForwarder(&_KeystoneForwarder.TransactOpts, forwarder) } -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Report(receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiverAddress, rawReport, reportContext, signatures) +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.RemoveForwarder(&_KeystoneForwarder.TransactOpts, forwarder) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "report", receiver, rawReport, reportContext, signatures) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactor) Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { + return _KeystoneForwarder.contract.Transact(opts, "route", transmissionId, transmitter, receiver, metadata, validatedReport) +} + +func (_KeystoneForwarder *KeystoneForwarderSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Route(&_KeystoneForwarder.TransactOpts, transmissionId, transmitter, receiver, metadata, validatedReport) +} + +func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { + return _KeystoneForwarder.Contract.Route(&_KeystoneForwarder.TransactOpts, transmissionId, transmitter, receiver, metadata, validatedReport) } func (_KeystoneForwarder *KeystoneForwarderTransactor) SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { @@ -297,6 +399,398 @@ func (_KeystoneForwarder *KeystoneForwarderTransactorSession) TransferOwnership( return _KeystoneForwarder.Contract.TransferOwnership(&_KeystoneForwarder.TransactOpts, to) } +type KeystoneForwarderConfigSetIterator struct { + Event *KeystoneForwarderConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *KeystoneForwarderConfigSetIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderConfigSet struct { + DonId uint32 + ConfigVersion uint32 + F uint8 + Signers []common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var configVersionRule []interface{} + for _, configVersionItem := range configVersion { + configVersionRule = append(configVersionRule, configVersionItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ConfigSet", donIdRule, configVersionRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderConfigSetIterator{contract: _KeystoneForwarder.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var configVersionRule []interface{} + for _, configVersionItem := range configVersion { + configVersionRule = append(configVersionRule, configVersionItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ConfigSet", donIdRule, configVersionRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderConfigSet) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) { + event := new(KeystoneForwarderConfigSet) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderForwarderAddedIterator struct { + Event *KeystoneForwarderForwarderAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderForwarderAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderForwarderAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderForwarderAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *KeystoneForwarderForwarderAddedIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderForwarderAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderForwarderAdded struct { + Forwarder common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderAddedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ForwarderAdded", forwarderRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderForwarderAddedIterator{contract: _KeystoneForwarder.contract, event: "ForwarderAdded", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderAdded, forwarder []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ForwarderAdded", forwarderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderForwarderAdded) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseForwarderAdded(log types.Log) (*KeystoneForwarderForwarderAdded, error) { + event := new(KeystoneForwarderForwarderAdded) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneForwarderForwarderRemovedIterator struct { + Event *KeystoneForwarderForwarderRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneForwarderForwarderRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderForwarderRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(KeystoneForwarderForwarderRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *KeystoneForwarderForwarderRemovedIterator) Error() error { + return it.fail +} + +func (it *KeystoneForwarderForwarderRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneForwarderForwarderRemoved struct { + Forwarder common.Address + Raw types.Log +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderRemovedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ForwarderRemoved", forwarderRule) + if err != nil { + return nil, err + } + return &KeystoneForwarderForwarderRemovedIterator{contract: _KeystoneForwarder.contract, event: "ForwarderRemoved", logs: logs, sub: sub}, nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderRemoved, forwarder []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ForwarderRemoved", forwarderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneForwarderForwarderRemoved) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseForwarderRemoved(log types.Log) (*KeystoneForwarderForwarderRemoved, error) { + event := new(KeystoneForwarderForwarderRemoved) + if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type KeystoneForwarderOwnershipTransferRequestedIterator struct { Event *KeystoneForwarderOwnershipTransferRequested @@ -632,11 +1126,12 @@ func (it *KeystoneForwarderReportProcessedIterator) Close() error { type KeystoneForwarderReportProcessed struct { Receiver common.Address WorkflowExecutionId [32]byte + ReportId [2]byte Result bool Raw types.Log } -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte) (*KeystoneForwarderReportProcessedIterator, error) { +func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) { var receiverRule []interface{} for _, receiverItem := range receiver { @@ -646,15 +1141,19 @@ func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts for _, workflowExecutionIdItem := range workflowExecutionId { workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) } + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule) + logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) if err != nil { return nil, err } return &KeystoneForwarderReportProcessedIterator{contract: _KeystoneForwarder.contract, event: "ReportProcessed", logs: logs, sub: sub}, nil } -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte) (event.Subscription, error) { +func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) { var receiverRule []interface{} for _, receiverItem := range receiver { @@ -664,8 +1163,12 @@ func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts * for _, workflowExecutionIdItem := range workflowExecutionId { workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) } + var reportIdRule []interface{} + for _, reportIdItem := range reportId { + reportIdRule = append(reportIdRule, reportIdItem) + } - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule) + logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) if err != nil { return nil, err } @@ -708,6 +1211,12 @@ func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseReportProcessed(log ty func (_KeystoneForwarder *KeystoneForwarder) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { + case _KeystoneForwarder.abi.Events["ConfigSet"].ID: + return _KeystoneForwarder.ParseConfigSet(log) + case _KeystoneForwarder.abi.Events["ForwarderAdded"].ID: + return _KeystoneForwarder.ParseForwarderAdded(log) + case _KeystoneForwarder.abi.Events["ForwarderRemoved"].ID: + return _KeystoneForwarder.ParseForwarderRemoved(log) case _KeystoneForwarder.abi.Events["OwnershipTransferRequested"].ID: return _KeystoneForwarder.ParseOwnershipTransferRequested(log) case _KeystoneForwarder.abi.Events["OwnershipTransferred"].ID: @@ -720,6 +1229,18 @@ func (_KeystoneForwarder *KeystoneForwarder) ParseLog(log types.Log) (generated. } } +func (KeystoneForwarderConfigSet) Topic() common.Hash { + return common.HexToHash("0x4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455") +} + +func (KeystoneForwarderForwarderAdded) Topic() common.Hash { + return common.HexToHash("0x0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e7") +} + +func (KeystoneForwarderForwarderRemoved) Topic() common.Hash { + return common.HexToHash("0xb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d38") +} + func (KeystoneForwarderOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -729,7 +1250,7 @@ func (KeystoneForwarderOwnershipTransferred) Topic() common.Hash { } func (KeystoneForwarderReportProcessed) Topic() common.Hash { - return common.HexToHash("0xbe015fd2fd7c1a00158e111095c794ae7030eb413d2a0990e5b78d3114df1d49") + return common.HexToHash("0x3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b5") } func (_KeystoneForwarder *KeystoneForwarder) Address() common.Address { @@ -737,22 +1258,52 @@ func (_KeystoneForwarder *KeystoneForwarder) Address() common.Address { } type KeystoneForwarderInterface interface { + GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) + + GetTransmissionState(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (uint8, error) + GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) + IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) + Owner(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) + ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) - Report(opts *bind.TransactOpts, receiverAddress common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) + RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) + + Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) + + Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) + + FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderAddedIterator, error) + + WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderAdded, forwarder []common.Address) (event.Subscription, error) + + ParseForwarderAdded(log types.Log) (*KeystoneForwarderForwarderAdded, error) + + FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderRemovedIterator, error) + + WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderRemoved, forwarder []common.Address) (event.Subscription, error) + + ParseForwarderRemoved(log types.Log) (*KeystoneForwarderForwarderRemoved, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) @@ -765,9 +1316,9 @@ type KeystoneForwarderInterface interface { ParseOwnershipTransferred(log types.Log) (*KeystoneForwarderOwnershipTransferred, error) - FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte) (*KeystoneForwarderReportProcessedIterator, error) + FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) - WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte) (event.Subscription, error) + WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) ParseReportProcessed(log types.Log) (*KeystoneForwarderReportProcessed, error) diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go deleted file mode 100644 index b4796e0423..0000000000 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ /dev/null @@ -1,2289 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package keystone_capability_registry - -import ( - "errors" - "fmt" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -type CapabilityRegistryCapability struct { - LabelledName string - Version string - CapabilityType uint8 - ResponseType uint8 - ConfigurationContract common.Address -} - -type CapabilityRegistryCapabilityConfiguration struct { - CapabilityId [32]byte - Config []byte -} - -type CapabilityRegistryDONInfo struct { - Id uint32 - ConfigCount uint32 - F uint32 - IsPublic bool - AcceptsWorkflows bool - NodeP2PIds [][32]byte - CapabilityConfigurations []CapabilityRegistryCapabilityConfiguration -} - -type CapabilityRegistryNodeInfo struct { - NodeOperatorId uint32 - Signer [32]byte - P2pId [32]byte - HashedCapabilityIds [][32]byte -} - -type CapabilityRegistryNodeOperator struct { - Admin common.Address - Name string -} - -var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilityRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilityRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo\",\"name\":\"\",\"type\":\"tuple\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodeInfo\",\"type\":\"tuple[]\"},{\"internalType\":\"uint32[]\",\"name\":\"configCounts\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilityRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"f\",\"type\":\"uint32\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.NodeInfo[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b614e6f80620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635d83d967116100ee57806386fa4246116100975780639cb7c5f4116100715780639cb7c5f4146103ea578063ddbe4f821461040a578063e29581aa14610420578063f2fde38b1461043657600080fd5b806386fa42461461039c5780638da5cb5b146103af57806395864d1f146103d757600080fd5b8063715f5295116100c8578063715f52951461036e57806373ac22b41461038157806379ba50971461039457600080fd5b80635d83d967146103335780635e65e3091461034657806366acaa331461035957600080fd5b806322bdbcbc1161015b5780632c01a1e8116101355780632c01a1e8146102cb578063398f3773146102de5780633f2a13c9146102f157806350c946fe1461031257600080fd5b806322bdbcbc146102785780632353740514610298578063275459f2146102b857600080fd5b8063193ec0061161018c578063193ec0061461023b5780631d05394c14610250578063214502431461026357600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613c70565b610449565b6040519081526020015b60405180910390f35b6101ec6101e7366004613cd4565b61047d565b60405190151581526020016101d0565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101d09190613d5b565b61024e610249366004613dda565b61048a565b005b61024e61025e366004613e7f565b610554565b61026b610710565b6040516101d09190613fe9565b61028b610286366004614069565b610875565b6040516101d091906140c1565b6102ab6102a6366004614069565b610962565b6040516101d091906140d4565b61024e6102c6366004613e7f565b6109a6565b61024e6102d9366004613e7f565b610a7d565b61024e6102ec366004613e7f565b610ca0565b6103046102ff3660046140e7565b610e68565b6040516101d0929190614111565b610325610320366004613cd4565b611054565b6040516101d0929190614178565b61024e610341366004613e7f565b6110f9565b61024e610354366004613e7f565b611247565b6103616116b9565b6040516101d091906141a0565b61024e61037c366004613e7f565b6118a4565b61024e61038f366004613e7f565b61195f565b61024e611e04565b61024e6103aa366004614213565b611f01565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b61024e6103e536600461427f565b612247565b6103fd6103f8366004613cd4565b612313565b6040516101d091906143f0565b610412612518565b6040516101d0929190614403565b610428612883565b6040516101d0929190614493565b61024e610444366004614576565b6129f2565b6000828260405160200161045e929190614111565b6040516020818303038152906040528051906020012090505b92915050565b6000610477600583612a06565b610492612a21565b600e805460009164010000000090910463ffffffff169060046104b4836145c0565b82546101009290920a63ffffffff8181021990931691831602179091558181166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a081018352928352600190830152871515908201528515156060820152908416608082015290915061054a908990899089908990612aa4565b5050505050505050565b61055c612a21565b60005b8181101561070b57600083838381811061057b5761057b6145e3565b90506020020160208101906105909190614069565b63ffffffff8082166000908152600d60209081526040808320805464010000000090049094168084526001850190925282209394509192905b6105d282613154565b81101561062a576106198563ffffffff16600c60006105fa858761315e90919063ffffffff16565b815260200190815260200160002060040161316a90919063ffffffff16565b5061062381614612565b90506105c9565b508254640100000000900463ffffffff16600003610681576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff851660048201526024015b60405180910390fd5b63ffffffff84166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffff00000000000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a1505050508061070490614612565b905061055f565b505050565b600e54606090640100000000900463ffffffff16600061073160018361464a565b63ffffffff1667ffffffffffffffff81111561074f5761074f613b0a565b6040519080825280602002602001820160405280156107d657816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161076d5790505b509050600060015b8363ffffffff168163ffffffff1610156108525763ffffffff8082166000908152600d602052604090205416156108425761081881613176565b83838151811061082a5761082a6145e3565b60200260200101819052508161083f90614612565b91505b61084b816145c0565b90506107de565b5061085e60018461464a565b63ffffffff16811461086e578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff16835260018101805491928401916108d990614667565b80601f016020809104026020016040519081016040528092919081815260200182805461090590614667565b80156109525780601f1061092757610100808354040283529160200191610952565b820191906000526020600020905b81548152906001019060200180831161093557829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261047782613176565b6109ae612a21565b60005b63ffffffff811682111561070b57600083838363ffffffff168181106109d9576109d96145e3565b90506020020160208101906109ee9190614069565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610a396001830182613a9d565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a250610a76816145c0565b90506109b1565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c9a576000848483818110610ab757610ab76145e3565b602090810292909201356000818152600c90935260409092206001810154929350919050610b14576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610678565b6000610b2282600401613154565b1115610b5d576040517f34a4a3f600000000000000000000000000000000000000000000000000000000815260048101839052602401610678565b83158015610b975750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610bd0576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610678565b6001810154610be19060079061316a565b506002810154610bf39060099061316a565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016815560018101829055600281018290559060048201818181610c488282613ad7565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610c7f91815260200190565b60405180910390a1505080610c9390614612565b9050610a9b565b50505050565b610ca8612a21565b60005b8181101561070b576000838383818110610cc757610cc76145e3565b9050602002810190610cd991906146ba565b610ce2906146f8565b805190915073ffffffffffffffffffffffffffffffffffffffff16610d33576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610dbf90826147b0565b5050600e8054909150600090610dda9063ffffffff166145c0565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610e4d9190613d5b565b60405180910390a3505080610e6190614612565b9050610cab565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610eba90614667565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee690614667565b8015610f335780601f10610f0857610100808354040283529160200191610f33565b820191906000526020600020905b815481529060010190602001808311610f1657829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611046905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015610ffd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261104391908101906148ca565b90505b9093509150505b9250929050565b6040805160808101825260008082526020820181905291810191909152606080820152604080516080810182526000848152600c6020908152838220805463ffffffff8082168652600183015484870152600283015486880152640100000000909104168352600301905291822060608201906110d090613452565b90526000938452600c602052604090932054929364010000000090930463ffffffff1692915050565b611101612a21565b60005b8181101561070b576000838383818110611120576111206145e3565b90506020020135905061113d816003612a0690919063ffffffff16565b611176576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610678565b61118160058261345f565b6111ba576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610678565b6000818152600260205260408120906111d38282613a9d565b6111e1600183016000613a9d565b5060020180547fffffffffffffffffffff0000000000000000000000000000000000000000000016905560405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a25061124081614612565b9050611104565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c9a576000848483818110611281576112816145e3565b90506020028101906112939190614938565b61129c9061496c565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549596509394919390928401916112f290614667565b80601f016020809104026020016040519081016040528092919081815260200182805461131e90614667565b801561136b5780601f106113405761010080835404028352916020019161136b565b820191906000526020600020905b81548152906001019060200180831161134e57829003601f168201915b50505050508152505090508315801561139b5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156113d4576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610678565b6040808301516000908152600c6020522060018101546114285782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161067891815260200190565b60208301511580611458575082602001518160010154141580156114585750602083015161145890600790612a06565b1561148f576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606083015180516000036114d157806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106789190614a3f565b8154640100000000900463ffffffff168260046114ed836145c0565b82546101009290920a63ffffffff8181021990931691831602179091558354640100000000900416905060005b82518110156115e557611550838281518110611538576115386145e3565b60200260200101516003612a0690919063ffffffff16565b61158857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106789190614a3f565b6115d483828151811061159d5761159d6145e3565b60200260200101518560030160008563ffffffff1663ffffffff16815260200190815260200160002061345f90919063ffffffff16565b506115de81614612565b905061151a565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909116178355604085015160028401556001830154602086015181146116575761163c60078261316a565b506020860151600185018190556116559060079061345f565b505b85516040808801516020808a015183519283529082015263ffffffff909216917f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a2505050505050806116b290614612565b9050611265565b600e5460609063ffffffff1660006116d260018361464a565b63ffffffff1667ffffffffffffffff8111156116f0576116f0613b0a565b60405190808252806020026020018201604052801561173657816020015b60408051808201909152600081526060602082015281526020019060019003908161170e5790505b509050600060015b8363ffffffff168163ffffffff16101561188e5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff161561187e5763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff16835260018101805491928401916117d290614667565b80601f01602080910402602001604051908101604052809291908181526020018280546117fe90614667565b801561184b5780601f106118205761010080835404028352916020019161184b565b820191906000526020600020905b81548152906001019060200180831161182e57829003601f168201915b505050505081525050838381518110611866576118666145e3565b60200260200101819052508161187b90614612565b91505b611887816145c0565b905061173e565b50600e5461085e9060019063ffffffff1661464a565b6118ac612a21565b60005b8181101561070b5760008383838181106118cb576118cb6145e3565b90506020028101906118dd9190614a52565b6118e690614a95565b905060006118fc82600001518360200151610449565b905061190960038261345f565b611942576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610678565b61194c818361346b565b50508061195890614612565b90506118af565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c9a576000848483818110611999576119996145e3565b90506020028101906119ab9190614938565b6119b49061496c565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191611a0a90614667565b80601f0160208091040260200160405190810160405280929190818152602001828054611a3690614667565b8015611a835780601f10611a5857610100808354040283529160200191611a83565b820191906000526020600020905b815481529060010190602001808311611a6657829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611ae95781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610678565b83158015611b0e5750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611b47576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610678565b6040808301516000908152600c60205220600181015415611b9c5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161067891815260200190565b6040830151611bdf5782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161067891815260200190565b60208301511580611bfc57506020830151611bfc90600790612a06565b15611c33576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611c7557806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106789190614a3f565b81548290600490611c9390640100000000900463ffffffff166145c0565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b8251811015611d3a57611cdc838281518110611538576115386145e3565b611d1457826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106789190614a3f565b611d2983828151811061159d5761159d6145e3565b50611d3381614612565b9050611cbe565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff91821617845560408601516002850155602086015160018501819055611d90916007919061345f16565b506040850151611da29060099061345f565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a2505050505080611dfd90614612565b905061197d565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610678565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b828114611f44576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610678565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561223f576000868683818110611f7c57611f7c6145e3565b9050602002016020810190611f919190614069565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16612000576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610678565b6000868685818110612014576120146145e3565b905060200281019061202691906146ba565b61202f906146f8565b805190915073ffffffffffffffffffffffffffffffffffffffff16612080576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff1633148015906120bd57503373ffffffffffffffffffffffffffffffffffffffff861614155b156120f6576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610678565b8051825473ffffffffffffffffffffffffffffffffffffffff9081169116141580612172575060208082015160405161212f9201613d5b565b60405160208183030381529060405280519060200120826001016040516020016121599190614b3b565b6040516020818303038152906040528051906020012014155b1561222b57805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906121cc90826147b0565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516122229190613d5b565b60405180910390a35b5050508061223890614612565b9050611f60565b505050505050565b61224f612a21565b63ffffffff8089166000908152600d60205260408120546401000000009004909116908190036122b3576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610678565b612308888888886040518060a001604052808f63ffffffff168152602001876122db906145c0565b97508763ffffffff1681526020018a1515815260200189151581526020018863ffffffff16815250612aa4565b505050505050505050565b6123436040805160a081018252606080825260208201529081016000815260200160008152600060209091015290565b60008281526002602052604090819020815160a0810190925280548290829061236b90614667565b80601f016020809104026020016040519081016040528092919081815260200182805461239790614667565b80156123e45780601f106123b9576101008083540402835291602001916123e4565b820191906000526020600020905b8154815290600101906020018083116123c757829003601f168201915b505050505081526020016001820180546123fd90614667565b80601f016020809104026020016040519081016040528092919081815260200182805461242990614667565b80156124765780601f1061244b57610100808354040283529160200191612476565b820191906000526020600020905b81548152906001019060200180831161245957829003601f168201915b5050509183525050600282015460209091019060ff16600381111561249d5761249d614334565b60038111156124ae576124ae614334565b81526020016002820160019054906101000a900460ff1660018111156124d6576124d6614334565b60018111156124e7576124e7614334565b81526002919091015462010000900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b60608060006125276003613452565b905060006125356005613154565b82516125419190614be4565b905060008167ffffffffffffffff81111561255e5761255e613b0a565b6040519080825280602002602001820160405280156125bf57816020015b6125ac6040805160a081018252606080825260208201529081016000815260200160008152600060209091015290565b81526020019060019003908161257c5790505b50905060008267ffffffffffffffff8111156125dd576125dd613b0a565b604051908082528060200260200182016040528015612606578160200160208202803683370190505b5090506000805b855181101561287557600086828151811061262a5761262a6145e3565b60200260200101519050612648816005612a0690919063ffffffff16565b6128645760008181526002602052604090819020815160a0810190925280548290829061267490614667565b80601f01602080910402602001604051908101604052809291908181526020018280546126a090614667565b80156126ed5780601f106126c2576101008083540402835291602001916126ed565b820191906000526020600020905b8154815290600101906020018083116126d057829003601f168201915b5050505050815260200160018201805461270690614667565b80601f016020809104026020016040519081016040528092919081815260200182805461273290614667565b801561277f5780601f106127545761010080835404028352916020019161277f565b820191906000526020600020905b81548152906001019060200180831161276257829003601f168201915b5050509183525050600282015460209091019060ff1660038111156127a6576127a6614334565b60038111156127b7576127b7614334565b81526020016002820160019054906101000a900460ff1660018111156127df576127df614334565b60018111156127f0576127f0614334565b81526002919091015462010000900473ffffffffffffffffffffffffffffffffffffffff16602090910152855186908590811061282f5761282f6145e3565b60200260200101819052508084848151811061284d5761284d6145e3565b602090810291909101015261286183614612565b92505b5061286e81614612565b905061260d565b509096919550909350505050565b60608060006128926009613452565b9050805167ffffffffffffffff8111156128ae576128ae613b0a565b60405190808252806020026020018201604052801561291d57816020015b60408051608081018252600080825260208083018290529282015260608082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816128cc5790505b509250805167ffffffffffffffff81111561293a5761293a613b0a565b604051908082528060200260200182016040528015612963578160200160208202803683370190505b50915060005b81518110156129ec57612994828281518110612987576129876145e3565b6020026020010151611054565b8583815181106129a6576129a66145e3565b602002602001018584815181106129bf576129bf6145e3565b602002602001018263ffffffff1663ffffffff168152508290525050806129e590614612565b9050612969565b50509091565b6129fa612a21565b612a03816136ff565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612aa2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610678565b565b805163ffffffff9081166000908152600d602090815260408083208286015185168452600101909152902060808301519091161580612af8575060808201518590612af0906001614bf7565b63ffffffff16115b15612b445760808201516040517fd5f5269100000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101869052604401610678565b6001826020015163ffffffff161115612bf057815163ffffffff166000908152600d602090815260408220908401516001918201918391612b85919061464a565b63ffffffff1663ffffffff168152602001908152602001600020905060005b612bad82613154565b811015612bed57612bdc846000015163ffffffff16600c60006105fa858760000161315e90919063ffffffff16565b50612be681614612565b9050612ba4565b50505b60005b85811015612cda57612c20878783818110612c1057612c106145e3565b859260209091020135905061345f565b612c81578251878783818110612c3857612c386145e3565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610678565b8251612cc99063ffffffff16600c60008a8a86818110612ca357612ca36145e3565b90506020020135815260200190815260200160002060040161345f90919063ffffffff16565b50612cd381614612565b9050612bf3565b5060005b83811015612fc65736858583818110612cf957612cf96145e3565b9050602002810190612d0b91906146ba565b9050612d1960038235612a06565b612d52576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610678565b612d5e60058235612a06565b15612d98576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610678565b8035600090815260038401602052604081208054612db590614667565b90501115612e015783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610678565b60005b87811015612f1357612ea88235600c60008c8c86818110612e2757612e276145e3565b9050602002013581526020019081526020016000206003016000600c60008e8e88818110612e5757612e576145e3565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612a0690919063ffffffff16565b612f0357888882818110612ebe57612ebe6145e3565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610678565b612f0c81614612565b9050612e04565b5060028301805460018101825560009182526020918290208335910155612f3c90820182614c14565b82356000908152600386016020526040902091612f5a919083614c79565b508351602080860151612fb592918435908c908c90612f7b90880188614c14565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506137f492505050565b50612fbf81614612565b9050612cde565b50604080830151835163ffffffff9081166000908152600d602090815284822080549415156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff90951694909417909355606086015186518316825284822080549115156d0100000000000000000000000000027fffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffff9092169190911790556080860151865183168252848220805491841668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff909216919091179055918501805186518316845292849020805493909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9093169290921790558351905191517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c158170365192613144929163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b6000610477825490565b6000612a1a83836138d5565b6000612a1a83836138ff565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d825284832080546401000000009004909116808452600190910182528483206002810180548751818602810186019098528088529596929591949390919083018282801561322757602002820191906000526020600020905b815481526020019060010190808311613213575b505050505090506000815167ffffffffffffffff81111561324a5761324a613b0a565b60405190808252806020026020018201604052801561329057816020015b6040805180820190915260008152606060208201528152602001906001900390816132685790505b50905060005b81518110156133b15760405180604001604052808483815181106132bc576132bc6145e3565b602002602001015181526020018560030160008685815181106132e1576132e16145e3565b60200260200101518152602001908152602001600020805461330290614667565b80601f016020809104026020016040519081016040528092919081815260200182805461332e90614667565b801561337b5780601f106133505761010080835404028352916020019161337b565b820191906000526020600020905b81548152906001019060200180831161335e57829003601f168201915b5050505050815250828281518110613395576133956145e3565b6020026020010181905250806133aa90614612565b9050613296565b506040805160e08101825263ffffffff8089166000818152600d60208181528683205480861687528b8616828801526801000000000000000081049095169686019690965260ff6c010000000000000000000000008504811615156060870152929091529093526d010000000000000000000000000090049091161515608082015260a0810161344085613452565b81526020019190915295945050505050565b60606000612a1a836139f2565b6000612a1a8383613a4e565b608081015173ffffffffffffffffffffffffffffffffffffffff16156135b957608081015173ffffffffffffffffffffffffffffffffffffffff163b1580613564575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa15801561353e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135629190614d94565b155b156135b95760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610678565b6000828152600260205260409020815182919081906135d890826147b0565b50602082015160018201906135ed90826147b0565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561362f5761362f614334565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600181111561367657613676614334565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b3373ffffffffffffffffffffffffffffffffffffffff82160361377e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610678565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff161561223f57600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c9061389b908690869086908b908d90600401614db1565b600060405180830381600087803b1580156138b557600080fd5b505af11580156138c9573d6000803e3d6000fd5b50505050505050505050565b60008260000182815481106138ec576138ec6145e3565b9060005260206000200154905092915050565b600081815260018301602052604081205480156139e8576000613923600183614be4565b855490915060009061393790600190614be4565b905081811461399c576000866000018281548110613957576139576145e3565b906000526020600020015490508087600001848154811061397a5761397a6145e3565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806139ad576139ad614e33565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610477565b6000915050610477565b606081600001805480602002602001604051908101604052809291908181526020018280548015613a4257602002820191906000526020600020905b815481526020019060010190808311613a2e575b50505050509050919050565b6000818152600183016020526040812054613a9557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610477565b506000610477565b508054613aa990614667565b6000825580601f10613ab9575050565b601f016020900490600052602060002090810190612a039190613af1565b5080546000825590600052602060002090810190612a0391905b5b80821115613b065760008155600101613af2565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613b5c57613b5c613b0a565b60405290565b60405160a0810167ffffffffffffffff81118282101715613b5c57613b5c613b0a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613bcc57613bcc613b0a565b604052919050565b600067ffffffffffffffff821115613bee57613bee613b0a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613c2b57600080fd5b8135613c3e613c3982613bd4565b613b85565b818152846020838601011115613c5357600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613c8357600080fd5b823567ffffffffffffffff80821115613c9b57600080fd5b613ca786838701613c1a565b93506020850135915080821115613cbd57600080fd5b50613cca85828601613c1a565b9150509250929050565b600060208284031215613ce657600080fd5b5035919050565b60005b83811015613d08578181015183820152602001613cf0565b50506000910152565b60008151808452613d29816020860160208601613ced565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612a1a6020830184613d11565b60008083601f840112613d8057600080fd5b50813567ffffffffffffffff811115613d9857600080fd5b6020830191508360208260051b850101111561104d57600080fd5b8015158114612a0357600080fd5b803563ffffffff81168114613dd557600080fd5b919050565b600080600080600080600060a0888a031215613df557600080fd5b873567ffffffffffffffff80821115613e0d57600080fd5b613e198b838c01613d6e565b909950975060208a0135915080821115613e3257600080fd5b50613e3f8a828b01613d6e565b9096509450506040880135613e5381613db3565b92506060880135613e6381613db3565b9150613e7160808901613dc1565b905092959891949750929550565b60008060208385031215613e9257600080fd5b823567ffffffffffffffff811115613ea957600080fd5b613eb585828601613d6e565b90969095509350505050565b600081518084526020808501945080840160005b83811015613ef157815187529582019590820190600101613ed5565b509495945050505050565b600063ffffffff80835116845260208181850151168186015260408281860151168187015260608501511515606087015260808501511515608087015260a0850151925060e060a0870152613f5460e0870184613ec1565b925060c085015186840360c08801528381518086528486019150848160051b870101858401935060005b82811015613fdb578782037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018452845180518352870151878301879052613fc887840182613d11565b9588019594880194925050600101613f7e565b509998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561405c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261404a858351613efc565b94509285019290850190600101614010565b5092979650505050505050565b60006020828403121561407b57600080fd5b612a1a82613dc1565b73ffffffffffffffffffffffffffffffffffffffff815116825260006020820151604060208501526140b96040850182613d11565b949350505050565b602081526000612a1a6020830184614084565b602081526000612a1a6020830184613efc565b600080604083850312156140fa57600080fd5b61410383613dc1565b946020939093013593505050565b6040815260006141246040830185613d11565b82810360208401526141368185613d11565b95945050505050565b63ffffffff8151168252602081015160208301526040810151604083015260006060820151608060608501526140b96080850182613ec1565b60408152600061418b604083018561413f565b905063ffffffff831660208301529392505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561405c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614201858351614084565b945092850192908501906001016141c7565b6000806000806040858703121561422957600080fd5b843567ffffffffffffffff8082111561424157600080fd5b61424d88838901613d6e565b9096509450602087013591508082111561426657600080fd5b5061427387828801613d6e565b95989497509550505050565b60008060008060008060008060c0898b03121561429b57600080fd5b6142a489613dc1565b9750602089013567ffffffffffffffff808211156142c157600080fd5b6142cd8c838d01613d6e565b909950975060408b01359150808211156142e657600080fd5b506142f38b828c01613d6e565b909650945050606089013561430781613db3565b9250608089013561431781613db3565b915061432560a08a01613dc1565b90509295985092959890939650565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000815160a0845261437860a0850182613d11565b9050602083015184820360208601526143918282613d11565b9150506040830151600481106143a9576143a9614334565b60408501526060830151600281106143c3576143c3614334565b606085015260809283015173ffffffffffffffffffffffffffffffffffffffff1692909301919091525090565b602081526000612a1a6020830184614363565b6040815260006144166040830185613ec1565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015614484577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0878403018552614472838351614363565b94860194925090850190600101614438565b50909998505050505050505050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015614508577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030185526144f686835161413f565b955093820193908201906001016144bc565b50508584038187015286518085528782019482019350915060005b8281101561454557845163ffffffff1684529381019392810192600101614523565b5091979650505050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114613dd557600080fd5b60006020828403121561458857600080fd5b612a1a82614552565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff8083168181036145d9576145d9614591565b6001019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361464357614643614591565b5060010190565b63ffffffff82811682821603908082111561086e5761086e614591565b600181811c9082168061467b57607f821691505b6020821081036146b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126146ee57600080fd5b9190910192915050565b60006040823603121561470a57600080fd5b6040516040810167ffffffffffffffff828210818311171561472e5761472e613b0a565b8160405261473b85614552565b8352602085013591508082111561475157600080fd5b5061475e36828601613c1a565b60208301525092915050565b601f82111561070b57600081815260208120601f850160051c810160208610156147915750805b601f850160051c820191505b8181101561223f5782815560010161479d565b815167ffffffffffffffff8111156147ca576147ca613b0a565b6147de816147d88454614667565b8461476a565b602080601f83116001811461483157600084156147fb5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561223f565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561487e5788860151825594840194600190910190840161485f565b50858210156148ba57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156148dc57600080fd5b815167ffffffffffffffff8111156148f357600080fd5b8201601f8101841361490457600080fd5b8051614912613c3982613bd4565b81815285602083850101111561492757600080fd5b614136826020830160208601613ced565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126146ee57600080fd5b60006080823603121561497e57600080fd5b614986613b39565b61498f83613dc1565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff808211156149c057600080fd5b9085019036601f8301126149d357600080fd5b8135818111156149e5576149e5613b0a565b8060051b91506149f6848301613b85565b8181529183018401918481019036841115614a1057600080fd5b938501935b83851015614a2e57843582529385019390850190614a15565b606087015250939695505050505050565b602081526000612a1a6020830184613ec1565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126146ee57600080fd5b803560028110613dd557600080fd5b600060a08236031215614aa757600080fd5b614aaf613b62565b823567ffffffffffffffff80821115614ac757600080fd5b614ad336838701613c1a565b83526020850135915080821115614ae957600080fd5b50614af636828601613c1a565b602083015250604083013560048110614b0e57600080fd5b6040820152614b1f60608401614a86565b6060820152614b3060808401614552565b608082015292915050565b6000602080835260008454614b4f81614667565b80848701526040600180841660008114614b705760018114614ba857614bd6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550614bd6565b896000528660002060005b85811015614bce5781548b8201860152908301908801614bb3565b8a0184019650505b509398975050505050505050565b8181038181111561047757610477614591565b63ffffffff81811683821601908082111561086e5761086e614591565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614c4957600080fd5b83018035915067ffffffffffffffff821115614c6457600080fd5b60200191503681900382131561104d57600080fd5b67ffffffffffffffff831115614c9157614c91613b0a565b614ca583614c9f8354614667565b8361476a565b6000601f841160018114614cf75760008515614cc15750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614d8d565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614d465786850135825560209485019460019092019101614d26565b5086821015614d81577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b600060208284031215614da657600080fd5b8151612a1a81613db3565b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff861115614dea57600080fd5b8560051b808860a0850137820182810360a09081016020850152614e1090820187613d11565b91505063ffffffff80851660408401528084166060840152509695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", -} - -var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI - -var CapabilityRegistryBin = CapabilityRegistryMetaData.Bin - -func DeployCapabilityRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CapabilityRegistry, error) { - parsed, err := CapabilityRegistryMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CapabilityRegistryBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &CapabilityRegistry{address: address, abi: *parsed, CapabilityRegistryCaller: CapabilityRegistryCaller{contract: contract}, CapabilityRegistryTransactor: CapabilityRegistryTransactor{contract: contract}, CapabilityRegistryFilterer: CapabilityRegistryFilterer{contract: contract}}, nil -} - -type CapabilityRegistry struct { - address common.Address - abi abi.ABI - CapabilityRegistryCaller - CapabilityRegistryTransactor - CapabilityRegistryFilterer -} - -type CapabilityRegistryCaller struct { - contract *bind.BoundContract -} - -type CapabilityRegistryTransactor struct { - contract *bind.BoundContract -} - -type CapabilityRegistryFilterer struct { - contract *bind.BoundContract -} - -type CapabilityRegistrySession struct { - Contract *CapabilityRegistry - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type CapabilityRegistryCallerSession struct { - Contract *CapabilityRegistryCaller - CallOpts bind.CallOpts -} - -type CapabilityRegistryTransactorSession struct { - Contract *CapabilityRegistryTransactor - TransactOpts bind.TransactOpts -} - -type CapabilityRegistryRaw struct { - Contract *CapabilityRegistry -} - -type CapabilityRegistryCallerRaw struct { - Contract *CapabilityRegistryCaller -} - -type CapabilityRegistryTransactorRaw struct { - Contract *CapabilityRegistryTransactor -} - -func NewCapabilityRegistry(address common.Address, backend bind.ContractBackend) (*CapabilityRegistry, error) { - abi, err := abi.JSON(strings.NewReader(CapabilityRegistryABI)) - if err != nil { - return nil, err - } - contract, err := bindCapabilityRegistry(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &CapabilityRegistry{address: address, abi: abi, CapabilityRegistryCaller: CapabilityRegistryCaller{contract: contract}, CapabilityRegistryTransactor: CapabilityRegistryTransactor{contract: contract}, CapabilityRegistryFilterer: CapabilityRegistryFilterer{contract: contract}}, nil -} - -func NewCapabilityRegistryCaller(address common.Address, caller bind.ContractCaller) (*CapabilityRegistryCaller, error) { - contract, err := bindCapabilityRegistry(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &CapabilityRegistryCaller{contract: contract}, nil -} - -func NewCapabilityRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*CapabilityRegistryTransactor, error) { - contract, err := bindCapabilityRegistry(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &CapabilityRegistryTransactor{contract: contract}, nil -} - -func NewCapabilityRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*CapabilityRegistryFilterer, error) { - contract, err := bindCapabilityRegistry(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &CapabilityRegistryFilterer{contract: contract}, nil -} - -func bindCapabilityRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := CapabilityRegistryMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_CapabilityRegistry *CapabilityRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CapabilityRegistry.Contract.CapabilityRegistryCaller.contract.Call(opts, result, method, params...) -} - -func (_CapabilityRegistry *CapabilityRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.CapabilityRegistryTransactor.contract.Transfer(opts) -} - -func (_CapabilityRegistry *CapabilityRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.CapabilityRegistryTransactor.contract.Transact(opts, method, params...) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CapabilityRegistry.Contract.contract.Call(opts, result, method, params...) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.contract.Transfer(opts) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([][32]byte, []CapabilityRegistryCapability, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilities") - - if err != nil { - return *new([][32]byte), *new([]CapabilityRegistryCapability), err - } - - out0 := *abi.ConvertType(out[0], new([][32]byte)).(*[][32]byte) - out1 := *abi.ConvertType(out[1], new([]CapabilityRegistryCapability)).(*[]CapabilityRegistryCapability) - - return out0, out1, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilities() ([][32]byte, []CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilities() ([][32]byte, []CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", hashedId) - - if err != nil { - return *new(CapabilityRegistryCapability), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilityRegistryCapability)).(*CapabilityRegistryCapability) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(hashedId [32]byte) (CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, hashedId) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(hashedId [32]byte) (CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, hashedId) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilityConfigs", donId, capabilityId) - - if err != nil { - return *new([]byte), *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) - - return out0, out1, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { - return _CapabilityRegistry.Contract.GetCapabilityConfigs(&_CapabilityRegistry.CallOpts, donId, capabilityId) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { - return _CapabilityRegistry.Contract.GetCapabilityConfigs(&_CapabilityRegistry.CallOpts, donId, capabilityId) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetDON(opts *bind.CallOpts, donId uint32) (CapabilityRegistryDONInfo, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getDON", donId) - - if err != nil { - return *new(CapabilityRegistryDONInfo), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilityRegistryDONInfo)).(*CapabilityRegistryDONInfo) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetDON(donId uint32) (CapabilityRegistryDONInfo, error) { - return _CapabilityRegistry.Contract.GetDON(&_CapabilityRegistry.CallOpts, donId) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetDON(donId uint32) (CapabilityRegistryDONInfo, error) { - return _CapabilityRegistry.Contract.GetDON(&_CapabilityRegistry.CallOpts, donId) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetDONs(opts *bind.CallOpts) ([]CapabilityRegistryDONInfo, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getDONs") - - if err != nil { - return *new([]CapabilityRegistryDONInfo), err - } - - out0 := *abi.ConvertType(out[0], new([]CapabilityRegistryDONInfo)).(*[]CapabilityRegistryDONInfo) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetDONs() ([]CapabilityRegistryDONInfo, error) { - return _CapabilityRegistry.Contract.GetDONs(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetDONs() ([]CapabilityRegistryDONInfo, error) { - return _CapabilityRegistry.Contract.GetDONs(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getHashedCapabilityId", labelledName, version) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { - return _CapabilityRegistry.Contract.GetHashedCapabilityId(&_CapabilityRegistry.CallOpts, labelledName, version) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { - return _CapabilityRegistry.Contract.GetHashedCapabilityId(&_CapabilityRegistry.CallOpts, labelledName, version) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNodeInfo, uint32, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getNode", p2pId) - - if err != nil { - return *new(CapabilityRegistryNodeInfo), *new(uint32), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilityRegistryNodeInfo)).(*CapabilityRegistryNodeInfo) - out1 := *abi.ConvertType(out[1], new(uint32)).(*uint32) - - return out0, out1, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetNode(p2pId [32]byte) (CapabilityRegistryNodeInfo, uint32, error) { - return _CapabilityRegistry.Contract.GetNode(&_CapabilityRegistry.CallOpts, p2pId) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNode(p2pId [32]byte) (CapabilityRegistryNodeInfo, uint32, error) { - return _CapabilityRegistry.Contract.GetNode(&_CapabilityRegistry.CallOpts, p2pId) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilityRegistryNodeOperator, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) - - if err != nil { - return *new(CapabilityRegistryNodeOperator), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilityRegistryNodeOperator)).(*CapabilityRegistryNodeOperator) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetNodeOperator(nodeOperatorId uint32) (CapabilityRegistryNodeOperator, error) { - return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(nodeOperatorId uint32) (CapabilityRegistryNodeOperator, error) { - return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodeOperators(opts *bind.CallOpts) ([]CapabilityRegistryNodeOperator, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getNodeOperators") - - if err != nil { - return *new([]CapabilityRegistryNodeOperator), err - } - - out0 := *abi.ConvertType(out[0], new([]CapabilityRegistryNodeOperator)).(*[]CapabilityRegistryNodeOperator) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetNodeOperators() ([]CapabilityRegistryNodeOperator, error) { - return _CapabilityRegistry.Contract.GetNodeOperators(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperators() ([]CapabilityRegistryNodeOperator, error) { - return _CapabilityRegistry.Contract.GetNodeOperators(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodes(opts *bind.CallOpts) (GetNodes, - - error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getNodes") - - outstruct := new(GetNodes) - if err != nil { - return *outstruct, err - } - - outstruct.NodeInfo = *abi.ConvertType(out[0], new([]CapabilityRegistryNodeInfo)).(*[]CapabilityRegistryNodeInfo) - outstruct.ConfigCounts = *abi.ConvertType(out[1], new([]uint32)).(*[]uint32) - - return *outstruct, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) GetNodes() (GetNodes, - - error) { - return _CapabilityRegistry.Contract.GetNodes(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodes() (GetNodes, - - error) { - return _CapabilityRegistry.Contract.GetNodes(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", hashedCapabilityId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { - return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, hashedCapabilityId) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { - return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, hashedCapabilityId) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) Owner() (common.Address, error) { - return _CapabilityRegistry.Contract.Owner(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) Owner() (common.Address, error) { - return _CapabilityRegistry.Contract.Owner(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_CapabilityRegistry *CapabilityRegistrySession) TypeAndVersion() (string, error) { - return _CapabilityRegistry.Contract.TypeAndVersion(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryCallerSession) TypeAndVersion() (string, error) { - return _CapabilityRegistry.Contract.TypeAndVersion(&_CapabilityRegistry.CallOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "acceptOwnership") -} - -func (_CapabilityRegistry *CapabilityRegistrySession) AcceptOwnership() (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilityRegistryCapability) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "addCapabilities", capabilities) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) AddCapabilities(capabilities []CapabilityRegistryCapability) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddCapabilities(&_CapabilityRegistry.TransactOpts, capabilities) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapabilities(capabilities []CapabilityRegistryCapability) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddCapabilities(&_CapabilityRegistry.TransactOpts, capabilities) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "addDON", nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddDON(&_CapabilityRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddDON(&_CapabilityRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "addNodes", nodes) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) AddNodes(nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddNodes(&_CapabilityRegistry.TransactOpts, nodes) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodes(nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.AddNodes(&_CapabilityRegistry.TransactOpts, nodes) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "deprecateCapabilities", hashedCapabilityIds) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.DeprecateCapabilities(&_CapabilityRegistry.TransactOpts, hashedCapabilityIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.DeprecateCapabilities(&_CapabilityRegistry.TransactOpts, hashedCapabilityIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "removeDONs", donIds) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.RemoveDONs(&_CapabilityRegistry.TransactOpts, donIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.RemoveDONs(&_CapabilityRegistry.TransactOpts, donIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.RemoveNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "removeNodes", removedNodeP2PIds) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.RemoveNodes(&_CapabilityRegistry.TransactOpts, removedNodeP2PIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.RemoveNodes(&_CapabilityRegistry.TransactOpts, removedNodeP2PIds) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.TransferOwnership(&_CapabilityRegistry.TransactOpts, to) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.TransferOwnership(&_CapabilityRegistry.TransactOpts, to) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "updateDON", donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.UpdateDON(&_CapabilityRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.UpdateDON(&_CapabilityRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "updateNodeOperators", nodeOperatorIds, nodeOperators) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.UpdateNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds, nodeOperators) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.UpdateNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds, nodeOperators) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "updateNodes", nodes) -} - -func (_CapabilityRegistry *CapabilityRegistrySession) UpdateNodes(nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.UpdateNodes(&_CapabilityRegistry.TransactOpts, nodes) -} - -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodes(nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.UpdateNodes(&_CapabilityRegistry.TransactOpts, nodes) -} - -type CapabilityRegistryCapabilityConfiguredIterator struct { - Event *CapabilityRegistryCapabilityConfigured - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryCapabilityConfiguredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryCapabilityConfigured) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryCapabilityConfigured) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryCapabilityConfiguredIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryCapabilityConfiguredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryCapabilityConfigured struct { - HashedCapabilityId [32]byte - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityConfiguredIterator, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryCapabilityConfiguredIterator{contract: _CapabilityRegistry.contract, event: "CapabilityConfigured", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryCapabilityConfigured) - if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityConfigured(log types.Log) (*CapabilityRegistryCapabilityConfigured, error) { - event := new(CapabilityRegistryCapabilityConfigured) - if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryCapabilityDeprecatedIterator struct { - Event *CapabilityRegistryCapabilityDeprecated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryCapabilityDeprecatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryCapabilityDeprecated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryCapabilityDeprecated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryCapabilityDeprecatedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryCapabilityDeprecatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryCapabilityDeprecated struct { - HashedCapabilityId [32]byte - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryCapabilityDeprecatedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryCapabilityDeprecated) - if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) { - event := new(CapabilityRegistryCapabilityDeprecated) - if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryConfigSetIterator struct { - Event *CapabilityRegistryConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryConfigSetIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryConfigSet struct { - DonId uint32 - ConfigCount uint32 - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterConfigSet(opts *bind.FilterOpts) (*CapabilityRegistryConfigSetIterator, error) { - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &CapabilityRegistryConfigSetIterator{contract: _CapabilityRegistry.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryConfigSet) (event.Subscription, error) { - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryConfigSet) - if err := _CapabilityRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseConfigSet(log types.Log) (*CapabilityRegistryConfigSet, error) { - event := new(CapabilityRegistryConfigSet) - if err := _CapabilityRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryNodeAddedIterator struct { - Event *CapabilityRegistryNodeAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryNodeAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryNodeAddedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryNodeAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryNodeAdded struct { - P2pId [32]byte - NodeOperatorId uint32 - Signer [32]byte - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilityRegistryNodeAddedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeAdded", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryNodeAddedIterator{contract: _CapabilityRegistry.contract, event: "NodeAdded", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeAdded", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryNodeAdded) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeAdded(log types.Log) (*CapabilityRegistryNodeAdded, error) { - event := new(CapabilityRegistryNodeAdded) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryNodeOperatorAddedIterator struct { - Event *CapabilityRegistryNodeOperatorAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryNodeOperatorAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeOperatorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeOperatorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryNodeOperatorAddedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryNodeOperatorAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryNodeOperatorAdded struct { - NodeOperatorId uint32 - Admin common.Address - Name string - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryNodeOperatorAddedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryNodeOperatorAdded) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) { - event := new(CapabilityRegistryNodeOperatorAdded) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryNodeOperatorRemovedIterator struct { - Event *CapabilityRegistryNodeOperatorRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryNodeOperatorRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeOperatorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeOperatorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryNodeOperatorRemovedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryNodeOperatorRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryNodeOperatorRemoved struct { - NodeOperatorId uint32 - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilityRegistryNodeOperatorRemovedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryNodeOperatorRemovedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorRemoved", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryNodeOperatorRemoved) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) { - event := new(CapabilityRegistryNodeOperatorRemoved) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryNodeOperatorUpdatedIterator struct { - Event *CapabilityRegistryNodeOperatorUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryNodeOperatorUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeOperatorUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeOperatorUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryNodeOperatorUpdatedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryNodeOperatorUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryNodeOperatorUpdated struct { - NodeOperatorId uint32 - Admin common.Address - Name string - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilityRegistryNodeOperatorUpdatedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryNodeOperatorUpdatedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorUpdated", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryNodeOperatorUpdated) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) { - event := new(CapabilityRegistryNodeOperatorUpdated) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryNodeRemovedIterator struct { - Event *CapabilityRegistryNodeRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryNodeRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryNodeRemovedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryNodeRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryNodeRemoved struct { - P2pId [32]byte - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeRemovedIterator, error) { - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeRemoved") - if err != nil { - return nil, err - } - return &CapabilityRegistryNodeRemovedIterator{contract: _CapabilityRegistry.contract, event: "NodeRemoved", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeRemoved) (event.Subscription, error) { - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryNodeRemoved) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeRemoved(log types.Log) (*CapabilityRegistryNodeRemoved, error) { - event := new(CapabilityRegistryNodeRemoved) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryNodeUpdatedIterator struct { - Event *CapabilityRegistryNodeUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryNodeUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryNodeUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryNodeUpdatedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryNodeUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryNodeUpdated struct { - P2pId [32]byte - NodeOperatorId uint32 - Signer [32]byte - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilityRegistryNodeUpdatedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeUpdated", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryNodeUpdatedIterator{contract: _CapabilityRegistry.contract, event: "NodeUpdated", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeUpdated", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryNodeUpdated) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeUpdated(log types.Log) (*CapabilityRegistryNodeUpdated, error) { - event := new(CapabilityRegistryNodeUpdated) - if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryOwnershipTransferRequestedIterator struct { - Event *CapabilityRegistryOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryOwnershipTransferRequestedIterator{contract: _CapabilityRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryOwnershipTransferRequested) - if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*CapabilityRegistryOwnershipTransferRequested, error) { - event := new(CapabilityRegistryOwnershipTransferRequested) - if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilityRegistryOwnershipTransferredIterator struct { - Event *CapabilityRegistryOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilityRegistryOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilityRegistryOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilityRegistryOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *CapabilityRegistryOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilityRegistryOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferredIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &CapabilityRegistryOwnershipTransferredIterator{contract: _CapabilityRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilityRegistryOwnershipTransferred) - if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*CapabilityRegistryOwnershipTransferred, error) { - event := new(CapabilityRegistryOwnershipTransferred) - if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type GetNodes struct { - NodeInfo []CapabilityRegistryNodeInfo - ConfigCounts []uint32 -} - -func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _CapabilityRegistry.abi.Events["CapabilityConfigured"].ID: - return _CapabilityRegistry.ParseCapabilityConfigured(log) - case _CapabilityRegistry.abi.Events["CapabilityDeprecated"].ID: - return _CapabilityRegistry.ParseCapabilityDeprecated(log) - case _CapabilityRegistry.abi.Events["ConfigSet"].ID: - return _CapabilityRegistry.ParseConfigSet(log) - case _CapabilityRegistry.abi.Events["NodeAdded"].ID: - return _CapabilityRegistry.ParseNodeAdded(log) - case _CapabilityRegistry.abi.Events["NodeOperatorAdded"].ID: - return _CapabilityRegistry.ParseNodeOperatorAdded(log) - case _CapabilityRegistry.abi.Events["NodeOperatorRemoved"].ID: - return _CapabilityRegistry.ParseNodeOperatorRemoved(log) - case _CapabilityRegistry.abi.Events["NodeOperatorUpdated"].ID: - return _CapabilityRegistry.ParseNodeOperatorUpdated(log) - case _CapabilityRegistry.abi.Events["NodeRemoved"].ID: - return _CapabilityRegistry.ParseNodeRemoved(log) - case _CapabilityRegistry.abi.Events["NodeUpdated"].ID: - return _CapabilityRegistry.ParseNodeUpdated(log) - case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: - return _CapabilityRegistry.ParseOwnershipTransferRequested(log) - case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: - return _CapabilityRegistry.ParseOwnershipTransferred(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (CapabilityRegistryCapabilityConfigured) Topic() common.Hash { - return common.HexToHash("0x04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae") -} - -func (CapabilityRegistryCapabilityDeprecated) Topic() common.Hash { - return common.HexToHash("0xdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21") -} - -func (CapabilityRegistryConfigSet) Topic() common.Hash { - return common.HexToHash("0xf264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651") -} - -func (CapabilityRegistryNodeAdded) Topic() common.Hash { - return common.HexToHash("0x74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05") -} - -func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { - return common.HexToHash("0x78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e") -} - -func (CapabilityRegistryNodeOperatorRemoved) Topic() common.Hash { - return common.HexToHash("0xa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a") -} - -func (CapabilityRegistryNodeOperatorUpdated) Topic() common.Hash { - return common.HexToHash("0x86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28") -} - -func (CapabilityRegistryNodeRemoved) Topic() common.Hash { - return common.HexToHash("0x5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb9753205") -} - -func (CapabilityRegistryNodeUpdated) Topic() common.Hash { - return common.HexToHash("0x4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b") -} - -func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (CapabilityRegistryOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { - return _CapabilityRegistry.address -} - -type CapabilityRegistryInterface interface { - GetCapabilities(opts *bind.CallOpts) ([][32]byte, []CapabilityRegistryCapability, error) - - GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) - - GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) - - GetDON(opts *bind.CallOpts, donId uint32) (CapabilityRegistryDONInfo, error) - - GetDONs(opts *bind.CallOpts) ([]CapabilityRegistryDONInfo, error) - - GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) - - GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNodeInfo, uint32, error) - - GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilityRegistryNodeOperator, error) - - GetNodeOperators(opts *bind.CallOpts) ([]CapabilityRegistryNodeOperator, error) - - GetNodes(opts *bind.CallOpts) (GetNodes, - - error) - - IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilityRegistryCapability) (*types.Transaction, error) - - AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) - - AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) - - AddNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) - - DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) - - RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) - - RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) - - RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilityRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint32) (*types.Transaction, error) - - UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) - - UpdateNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNodeInfo) (*types.Transaction, error) - - FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityConfiguredIterator, error) - - WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) - - ParseCapabilityConfigured(log types.Log) (*CapabilityRegistryCapabilityConfigured, error) - - FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) - - WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) - - ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) - - FilterConfigSet(opts *bind.FilterOpts) (*CapabilityRegistryConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*CapabilityRegistryConfigSet, error) - - FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilityRegistryNodeAddedIterator, error) - - WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) - - ParseNodeAdded(log types.Log) (*CapabilityRegistryNodeAdded, error) - - FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) - - WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) - - ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) - - FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilityRegistryNodeOperatorRemovedIterator, error) - - WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) - - ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) - - FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilityRegistryNodeOperatorUpdatedIterator, error) - - WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) - - ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) - - FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilityRegistryNodeRemovedIterator, error) - - WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeRemoved) (event.Subscription, error) - - ParseNodeRemoved(log types.Log) (*CapabilityRegistryNodeRemoved, error) - - FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilityRegistryNodeUpdatedIterator, error) - - WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) - - ParseNodeUpdated(log types.Log) (*CapabilityRegistryNodeUpdated, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*CapabilityRegistryOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*CapabilityRegistryOwnershipTransferred, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go b/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go index ad1173b3ac..e51f4762d8 100644 --- a/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go +++ b/core/gethwrappers/keystone/generated/ocr3_capability/ocr3_capability.go @@ -31,8 +31,8 @@ var ( ) var OCR3CapabilityMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportingUnsupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"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\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"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\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50600133806000816200006b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009e576200009e81620000ac565b505050151560805262000157565b336001600160a01b03821603620001065760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000062565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611f7d6200017360003960006104a40152611f7d6000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80638da5cb5b11610076578063b1dc65a41161005b578063b1dc65a414610187578063e3d0e7121461019a578063f2fde38b146101ad57600080fd5b80638da5cb5b1461013f578063afcb95d71461016757600080fd5b8063181f5a77146100a857806379ba5097146100f057806381411834146100fa57806381ff70481461010f575b600080fd5b604080518082018252600e81527f4b657973746f6e6520302e302e30000000000000000000000000000000000000602082015290516100e791906117e8565b60405180910390f35b6100f86101c0565b005b6101026102c2565b6040516100e79190611853565b6004546002546040805163ffffffff808516825264010000000090940490931660208401528201526060016100e7565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e7565b6040805160018152600060208201819052918101919091526060016100e7565b6100f86101953660046118b2565b610331565b6100f86101a8366004611b7c565b610a62565b6100f86101bb366004611c49565b61143d565b60015473ffffffffffffffffffffffffffffffffffffffff163314610246576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6060600780548060200260200160405190810160405280929190818152602001828054801561032757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102fc575b5050505050905090565b60005a604080516020601f8b018190048102820181019092528981529192508a3591818c01359161038791849163ffffffff851691908e908e908190840183828082843760009201919091525061145192505050565b6103bd576040517f0be3632800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805183815262ffffff600884901c1660208201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16040805160608101825260025480825260035460ff80821660208501526101009091041692820192909252908314610492576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f6e666967446967657374206d69736d617463680000000000000000000000604482015260640161023d565b6104a08b8b8b8b8b8b61145a565b60007f0000000000000000000000000000000000000000000000000000000000000000156104fd576002826020015183604001516104de9190611cc2565b6104e89190611ce1565b6104f3906001611cc2565b60ff169050610513565b602082015161050d906001611cc2565b60ff1690505b88811461057c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e617475726573000000000000604482015260640161023d565b8887146105e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e0000604482015260640161023d565b3360009081526005602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561062857610628611d2a565b600281111561063957610639611d2a565b905250905060028160200151600281111561065657610656611d2a565b14801561069d57506007816000015160ff168154811061067857610678611c64565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610703576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015260640161023d565b5050505050610710611765565b6000808a8a604051610723929190611d59565b60405190819003812061073a918e90602001611d69565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b89811015610a445760006001848984602081106107a3576107a3611c64565b6107b091901a601b611cc2565b8e8e868181106107c2576107c2611c64565b905060200201358d8d878181106107db576107db611c64565b9050602002013560405160008152602001604052604051610818949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561083a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526005602090815290849020838501909452835460ff808216855292965092945084019161010090041660028111156108ba576108ba611d2a565b60028111156108cb576108cb611d2a565b90525092506001836020015160028111156108e8576108e8611d2a565b1461094f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e0000604482015260640161023d565b8251600090879060ff16601f811061096957610969611c64565b602002015173ffffffffffffffffffffffffffffffffffffffff16146109eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e6174757265000000000000000000000000604482015260640161023d565b8086846000015160ff16601f8110610a0557610a05611c64565b73ffffffffffffffffffffffffffffffffffffffff9092166020929092020152610a30600186611cc2565b94505080610a3d90611d7d565b9050610784565b505050610a55833383858e8e611511565b5050505050505050505050565b855185518560ff16601f831115610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e65727300000000000000000000000000000000604482015260640161023d565b60008111610b3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f7369746976650000000000000000000000000000604482015260640161023d565b818314610bcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e00000000000000000000000000000000000000000000000000000000606482015260840161023d565b610bd8816003611db5565b8311610c40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f20686967680000000000000000604482015260640161023d565b610c48611543565b6040805160c0810182528a8152602081018a905260ff8916918101919091526060810187905267ffffffffffffffff8616608082015260a081018590525b60065415610e3b57600654600090610ca090600190611dcc565b9050600060068281548110610cb757610cb7611c64565b60009182526020822001546007805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110610cf157610cf1611c64565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526005909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600680549192509080610d7157610d71611ddf565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556007805480610dda57610dda611ddf565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550610c86915050565b60005b8151518110156112a05760006005600084600001518481518110610e6457610e64611c64565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610eae57610eae611d2a565b14610f15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015260640161023d565b6040805180820190915260ff82168152600160208201528251805160059160009185908110610f4657610f46611c64565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610fe757610fe7611d2a565b021790555060009150610ff79050565b600560008460200151848151811061101157611011611c64565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff16600281111561105b5761105b611d2a565b146110c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015260640161023d565b6040805180820190915260ff8216815260208101600281525060056000846020015184815181106110f5576110f5611c64565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561119657611196611d2a565b0217905550508251805160069250839081106111b4576111b4611c64565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558201518051600791908390811061123057611230611c64565b60209081029190910181015182546001810184556000938452919092200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905561129981611d7d565b9050610e3e565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff811664010000000063ffffffff438116820292831785559083048116936001939092600092611332928692908216911617611e0e565b92506101000a81548163ffffffff021916908363ffffffff1602179055506113914630600460009054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a001516115c6565b6002819055825180516003805460ff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff90921691909117905560045460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0598611430988b98919763ffffffff909216969095919491939192611e32565b60405180910390a1610a55565b611445611543565b61144e81611670565b50565b60019392505050565b6000611467826020611db5565b611472856020611db5565b61147e88610144611ec8565b6114889190611ec8565b6114929190611ec8565b61149d906000611ec8565b9050368114611508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d617463680000000000000000604482015260640161023d565b50505050505050565b6040517f0750181900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146115c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161023d565b565b6000808a8a8a8a8a8a8a8a8a6040516020016115ea99989796959493929190611edb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036116ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161023d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b604051806103e00160405280601f906020820280368337509192915050565b6000815180845260005b818110156117aa5760208185018101518683018201520161178e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006117fb6020830184611784565b9392505050565b600081518084526020808501945080840160005b8381101561184857815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611816565b509495945050505050565b6020815260006117fb6020830184611802565b60008083601f84011261187857600080fd5b50813567ffffffffffffffff81111561189057600080fd5b6020830191508360208260051b85010111156118ab57600080fd5b9250929050565b60008060008060008060008060e0898b0312156118ce57600080fd5b606089018a8111156118df57600080fd5b8998503567ffffffffffffffff808211156118f957600080fd5b818b0191508b601f83011261190d57600080fd5b81358181111561191c57600080fd5b8c602082850101111561192e57600080fd5b6020830199508098505060808b013591508082111561194c57600080fd5b6119588c838d01611866565b909750955060a08b013591508082111561197157600080fd5b5061197e8b828c01611866565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611a0d57611a0d611997565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611a3957600080fd5b919050565b600082601f830112611a4f57600080fd5b8135602067ffffffffffffffff821115611a6b57611a6b611997565b8160051b611a7a8282016119c6565b9283528481018201928281019087851115611a9457600080fd5b83870192505b84831015611aba57611aab83611a15565b82529183019190830190611a9a565b979650505050505050565b803560ff81168114611a3957600080fd5b600082601f830112611ae757600080fd5b813567ffffffffffffffff811115611b0157611b01611997565b611b3260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016119c6565b818152846020838601011115611b4757600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff81168114611a3957600080fd5b60008060008060008060c08789031215611b9557600080fd5b863567ffffffffffffffff80821115611bad57600080fd5b611bb98a838b01611a3e565b97506020890135915080821115611bcf57600080fd5b611bdb8a838b01611a3e565b9650611be960408a01611ac5565b95506060890135915080821115611bff57600080fd5b611c0b8a838b01611ad6565b9450611c1960808a01611b64565b935060a0890135915080821115611c2f57600080fd5b50611c3c89828a01611ad6565b9150509295509295509295565b600060208284031215611c5b57600080fd5b6117fb82611a15565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160190811115611cdb57611cdb611c93565b92915050565b600060ff831680611d1b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611dae57611dae611c93565b5060010190565b8082028115828204841417611cdb57611cdb611c93565b81810381811115611cdb57611cdb611c93565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115611e2b57611e2b611c93565b5092915050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152611e628184018a611802565b90508281036080840152611e768189611802565b905060ff871660a084015282810360c0840152611e938187611784565b905067ffffffffffffffff851660e0840152828103610100840152611eb88185611784565b9c9b505050505050505050505050565b80820180821115611cdb57611cdb611c93565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152611f228285018b611802565b91508382036080850152611f36828a611802565b915060ff881660a085015283820360c0850152611f538288611784565b90861660e08501528381036101008501529050611eb8818561178456fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"ReportInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportingUnsupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"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\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"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\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"transmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fe180620001606000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80638da5cb5b11610076578063b1dc65a41161005b578063b1dc65a4146101c4578063e3d0e712146101d7578063f2fde38b146101ea57600080fd5b80638da5cb5b1461017c578063afcb95d7146101a457600080fd5b8063181f5a77146100a857806379ba5097146100f057806381411834146100fa57806381ff70481461010f575b600080fd5b604080518082018252600e81527f4b657973746f6e6520312e302e30000000000000000000000000000000000000602082015290516100e79190611883565b60405180910390f35b6100f86101fd565b005b6101026102ff565b6040516100e791906118ef565b61015960015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff9485168152939092166020840152908201526060016100e7565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e7565b6040805160018152600060208201819052918101919091526060016100e7565b6100f86101d236600461194e565b61036e565b6100f86101e5366004611c18565b610975565b6100f86101f8366004611ce5565b6114e0565b60015473ffffffffffffffffffffffffffffffffffffffff163314610283576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6060600680548060200260200160405190810160405280929190818152602001828054801561036457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610339575b5050505050905090565b60005a604080518b3580825262ffffff6020808f0135600881901c929092169084015293945092917fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a16103cf8a8a8a8a8a8a6114f4565b6003546000906002906103ed9060ff80821691610100900416611d5e565b6103f79190611d7d565b610402906001611d5e565b60ff169050878114610470576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e617475726573000000000000604482015260640161027a565b8786146104ff576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f7265706f727420727320616e64207373206d757374206265206f66206571756160448201527f6c206c656e677468000000000000000000000000000000000000000000000000606482015260840161027a565b3360009081526004602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561054257610542611dc6565b600281111561055357610553611dc6565b905250905060028160200151600281111561057057610570611dc6565b141580156105b957506006816000015160ff168154811061059357610593611d00565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff163314155b15610620576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f756e617574686f72697a6564207472616e736d69747465720000000000000000604482015260640161027a565b5050505061062c611800565b6000808a8a60405161063f929190611df5565b604051908190038120610656918e90602001611e05565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120838301909252600080845290830152915060005b898110156109575760006001848984602081106106bf576106bf611d00565b6106cc91901a601b611d5e565b8e8e868181106106de576106de611d00565b905060200201358d8d878181106106f7576106f7611d00565b9050602002013560405160008152602001604052604051610734949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610756573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff811660009081526004602090815290849020838501909452835460ff808216855292965092945084019161010090041660028111156107d6576107d6611dc6565b60028111156107e7576107e7611dc6565b905250925060018360200151600281111561080457610804611dc6565b1461086b576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f61646472657373206e6f7420617574686f72697a656420746f207369676e0000604482015260640161027a565b8251600090879060ff16601f811061088557610885611d00565b602002015173ffffffffffffffffffffffffffffffffffffffff1614610907576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6e6f6e2d756e69717565207369676e6174757265000000000000000000000000604482015260640161027a565b8086846000015160ff16601f811061092157610921611d00565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015261094c600186611d5e565b9450506001016106a0565b505050610968833383858e8e6115ab565b5050505050505050505050565b855185518560ff16601f8311156109e8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e65727300000000000000000000000000000000604482015260640161027a565b80600003610a52576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f7369746976650000000000000000000000000000604482015260640161027a565b818314610ae0576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e00000000000000000000000000000000000000000000000000000000606482015260840161027a565b610aeb816003611e19565b8311610b53576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f20686967680000000000000000604482015260640161027a565b610b5b6115dd565b6040805160c0810182528a8152602081018a905260ff8916918101919091526060810187905267ffffffffffffffff8616608082015260a081018590525b60055415610d4e57600554600090610bb390600190611e30565b9050600060058281548110610bca57610bca611d00565b60009182526020822001546006805473ffffffffffffffffffffffffffffffffffffffff90921693509084908110610c0457610c04611d00565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff85811684526004909252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090811690915592909116808452922080549091169055600580549192509080610c8457610c84611e43565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190556006805480610ced57610ced611e43565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905501905550610b99915050565b60005b8151518110156112fd57815180516000919083908110610d7357610d73611d00565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610df8576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f7369676e6572206d757374206e6f7420626520656d7074790000000000000000604482015260640161027a565b600073ffffffffffffffffffffffffffffffffffffffff1682602001518281518110610e2657610e26611d00565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603610eab576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d707479000000604482015260640161027a565b60006004600084600001518481518110610ec757610ec7611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff166002811115610f1157610f11611dc6565b14610f78576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f7265706561746564207369676e65722061646472657373000000000000000000604482015260640161027a565b6040805180820190915260ff82168152600160208201528251805160049160009185908110610fa957610fa9611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561104a5761104a611dc6565b02179055506000915061105a9050565b600460008460200151848151811061107457611074611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002054610100900460ff1660028111156110be576110be611dc6565b14611125576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d6974746572206164647265737300000000604482015260640161027a565b6040805180820190915260ff82168152602081016002815250600460008460200151848151811061115857611158611d00565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156111f9576111f9611dc6565b02179055505082518051600592508390811061121757611217611d00565b602090810291909101810151825460018101845560009384529282902090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558201518051600691908390811061129357611293611d00565b60209081029190910181015182546001808201855560009485529290932090920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915501610d51565b506040810151600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916113b591849174010000000000000000000000000000000000000000900416611e72565b92506101000a81548163ffffffff021916908363ffffffff1602179055506114144630600160149054906101000a900463ffffffff1663ffffffff16856000015186602001518760400151886060015189608001518a60a00151611660565b600281905582518051600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff9093169290920291909117905560015460208501516040808701516060880151608089015160a08a015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e05986114cb988b9891977401000000000000000000000000000000000000000090920463ffffffff16969095919491939192611e96565b60405180910390a15050505050505050505050565b6114e86115dd565b6114f18161170b565b50565b6000611501826020611e19565b61150c856020611e19565b61151888610144611f2c565b6115229190611f2c565b61152c9190611f2c565b611537906000611f2c565b90503681146115a2576040517f660bd4ba00000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d617463680000000000000000604482015260640161027a565b50505050505050565b6040517f0750181900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461165e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161027a565b565b6000808a8a8a8a8a8a8a8a8a60405160200161168499989796959493929190611f3f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff82160361178a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161027a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b604051806103e00160405280601f906020820280368337509192915050565b6000815180845260005b8181101561184557602081850181015186830182015201611829565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611896602083018461181f565b9392505050565b60008151808452602080850194506020840160005b838110156118e457815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016118b2565b509495945050505050565b602081526000611896602083018461189d565b60008083601f84011261191457600080fd5b50813567ffffffffffffffff81111561192c57600080fd5b6020830191508360208260051b850101111561194757600080fd5b9250929050565b60008060008060008060008060e0898b03121561196a57600080fd5b606089018a81111561197b57600080fd5b8998503567ffffffffffffffff8082111561199557600080fd5b818b0191508b601f8301126119a957600080fd5b8135818111156119b857600080fd5b8c60208285010111156119ca57600080fd5b6020830199508098505060808b01359150808211156119e857600080fd5b6119f48c838d01611902565b909750955060a08b0135915080821115611a0d57600080fd5b50611a1a8b828c01611902565b999c989b50969995989497949560c00135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611aa957611aa9611a33565b604052919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611ad557600080fd5b919050565b600082601f830112611aeb57600080fd5b8135602067ffffffffffffffff821115611b0757611b07611a33565b8160051b611b16828201611a62565b9283528481018201928281019087851115611b3057600080fd5b83870192505b84831015611b5657611b4783611ab1565b82529183019190830190611b36565b979650505050505050565b803560ff81168114611ad557600080fd5b600082601f830112611b8357600080fd5b813567ffffffffffffffff811115611b9d57611b9d611a33565b611bce60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611a62565b818152846020838601011115611be357600080fd5b816020850160208301376000918101602001919091529392505050565b803567ffffffffffffffff81168114611ad557600080fd5b60008060008060008060c08789031215611c3157600080fd5b863567ffffffffffffffff80821115611c4957600080fd5b611c558a838b01611ada565b97506020890135915080821115611c6b57600080fd5b611c778a838b01611ada565b9650611c8560408a01611b61565b95506060890135915080821115611c9b57600080fd5b611ca78a838b01611b72565b9450611cb560808a01611c00565b935060a0890135915080821115611ccb57600080fd5b50611cd889828a01611b72565b9150509295509295509295565b600060208284031215611cf757600080fd5b61189682611ab1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160190811115611d7757611d77611d2f565b92915050565b600060ff831680611db7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b8060ff84160491505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8183823760009101908152919050565b828152606082602083013760800192915050565b8082028115828204841417611d7757611d77611d2f565b81810381811115611d7757611d77611d2f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b63ffffffff818116838216019080821115611e8f57611e8f611d2f565b5092915050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152611ec68184018a61189d565b90508281036080840152611eda818961189d565b905060ff871660a084015282810360c0840152611ef7818761181f565b905067ffffffffffffffff851660e0840152828103610100840152611f1c818561181f565b9c9b505050505050505050505050565b80820180821115611d7757611d77611d2f565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152611f868285018b61189d565b91508382036080850152611f9a828a61189d565b915060ff881660a085015283820360c0850152611fb7828861181f565b90861660e08501528381036101008501529050611f1c818561181f56fea164736f6c6343000818000a", } var OCR3CapabilityABI = OCR3CapabilityMetaData.ABI diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 605607aeb9..4051f95020 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 -forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin ec6e94293700d400ca7b22989d54793e905d6febce3b84054727a58c473b9cf3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 2913d0d38f6a6edc6d437e16d042c7a6732171213c096259f2113170550e925e -ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 +capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 3a082f0307411f41c30db26e61d59adcd5b003141a5aa8fe79d7779619028e26 +forwarder: ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin dc98a86a3775ead987b79d5b6079ee0e26f31c0626032bdd6508f986e2423227 +ocr3_capability: ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin 8bf0f53f222efce7143dea6134552eb26ea1eef845407b4475a0d79b7d7ba9f8 diff --git a/core/gethwrappers/keystone/go_generate.go b/core/gethwrappers/keystone/go_generate.go index 679b678b8f..36b27852ad 100644 --- a/core/gethwrappers/keystone/go_generate.go +++ b/core/gethwrappers/keystone/go_generate.go @@ -4,6 +4,6 @@ package gethwrappers // Keystone -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin KeystoneForwarder forwarder -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin OCR3Capability ocr3_capability -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin CapabilityRegistry keystone_capability_registry +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin KeystoneForwarder forwarder +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin OCR3Capability ocr3_capability +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin CapabilitiesRegistry capabilities_registry diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index ae87baa564..440f68d893 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -319,6 +319,8 @@ fromBlock = %d if test.chainReaderAndCodec { chainReaderSpec = ` [relayConfig.chainReader.contracts.median] +contractPollingFilter.genericEventNames = ["LatestRoundRequested"] + contractABI = ''' [ { diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 169f18f227..c0167a7d02 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -25,8 +25,8 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.17 - github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce + github.com/smartcontractkit/chainlink-automation v1.0.4 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c @@ -38,6 +38,7 @@ require ( github.com/urfave/cli v1.22.14 go.dedis.ch/kyber/v3 v3.1.0 go.uber.org/multierr v1.11.0 + google.golang.org/protobuf v1.33.0 k8s.io/api v0.30.0 k8s.io/apimachinery v0.30.0 k8s.io/client-go v0.30.0 @@ -348,7 +349,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 87394ca6be..b8cf2508e5 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1206,10 +1206,10 @@ 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.17 h1:otOlYUnutS8oQBEAi9RLQICqZP0Nxy0k8vOZuSMJa4w= github.com/smartcontractkit/chain-selectors v1.0.17/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= -github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= +github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 h1:6322qmPgHgYF/d/NjjbuZvF0Qfz4Hp+wLtLeS3SA3mI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/scripts/keystone/05_deploy_and_initialize_capabilities_registry-sample.sh b/core/scripts/keystone/05_deploy_and_initialize_capabilities_registry-sample.sh new file mode 100755 index 0000000000..21c764be0e --- /dev/null +++ b/core/scripts/keystone/05_deploy_and_initialize_capabilities_registry-sample.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +go run main.go \ + deploy-and-initialize-capabilities-registry \ + --chainid=11155111 \ + --ethurl=$ETH_URL \ + --accountkey=$ACCOUNT_KEY \ + --craddress=$CR_ADDRESS \ // 0x0d36aAC2Fd9d6d1C1F59251be6A2B337af27C52B diff --git a/core/scripts/keystone/main.go b/core/scripts/keystone/main.go index 4b48ba84f5..571623578a 100644 --- a/core/scripts/keystone/main.go +++ b/core/scripts/keystone/main.go @@ -19,6 +19,7 @@ func main() { src.NewDeployJobSpecsCommand(), src.NewGenerateCribClusterOverridesCommand(), src.NewDeleteJobsCommand(), + src.NewDeployAndInitializeCapabilitiesRegistryCommand(), } commandsList := func(commands []command) string { diff --git a/core/scripts/keystone/ocr_config.json b/core/scripts/keystone/ocr_config.json index cb490d3fa4..31fe898805 100644 --- a/core/scripts/keystone/ocr_config.json +++ b/core/scripts/keystone/ocr_config.json @@ -14,7 +14,7 @@ "DeltaCertifiedCommitRequestMillis": 1000, "DeltaStageMillis": 30000, "MaxRoundsPerEpoch": 10, - "TransmissionSchedule": [4], + "TransmissionSchedule": [7], "MaxDurationQueryMillis": 1000, "MaxDurationObservationMillis": 1000, diff --git a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go new file mode 100644 index 0000000000..291ef13149 --- /dev/null +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -0,0 +1,374 @@ +package src + +import ( + "context" + "encoding/hex" + "flag" + "fmt" + "log" + "os" + "strings" + + "github.com/ethereum/go-ethereum/common" + ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + "google.golang.org/protobuf/proto" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +type peer struct { + PeerID string + Signer string +} + +var ( + workflowDonPeers = []peer{ + { + PeerID: "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", + Signer: "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d", + }, + { + PeerID: "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", + Signer: "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d", + }, + { + PeerID: "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", + Signer: "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C", + }, + { + PeerID: "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", + Signer: "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF", + }, + { + PeerID: "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97", + Signer: "0x8F572978673d711b2F061EB7d514BD46EAD6668A", + }, + { + PeerID: "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA", + Signer: "0x21eF07Dfaf8f7C10CB0d53D18b641ee690541f9D", + }, + { + PeerID: "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX", + Signer: "0x7Fa21F6f716CFaF8f249564D72Ce727253186C89", + }, + } + triggerDonPeers = []peer{ + { + PeerID: "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m", + Signer: "0x9CcE7293a4Cc2621b61193135A95928735e4795F", + }, + { + PeerID: "12D3KooWS7JSY9fzSfWgbCE1S3W2LNY6ZVpRuun74moVBkKj6utE", + Signer: "0x3c775F20bCB2108C1A818741Ce332Bb5fe0dB925", + }, + { + PeerID: "12D3KooWMMTDXcWhpVnwrdAer1jnVARTmnr3RyT3v7Djg8ZuoBh9", + Signer: "0x50314239e2CF05555ceeD53E7F47eB2A8Eab0dbB", + }, + { + PeerID: "12D3KooWGzVXsKxXsF4zLgxSDM8Gzx1ywq2pZef4PrHMKuVg4K3P", + Signer: "0xd76A4f98898c3b9A72b244476d7337b50D54BCd8", + }, + { + PeerID: "12D3KooWSyjmmzjVtCzwN7bXzZQFmWiJRuVcKBerNjVgL7HdLJBW", + Signer: "0x656A873f6895b8a03Fb112dE927d43FA54B2c92A", + }, + { + PeerID: "12D3KooWLGz9gzhrNsvyM6XnXS3JRkZoQdEzuAvysovnSChNK5ZK", + Signer: "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553", + }, + { + PeerID: "12D3KooWAvZnvknFAfSiUYjATyhzEJLTeKvAzpcLELHi4ogM3GET", + Signer: "0x91d9b0062265514f012Eb8fABA59372fD9520f56", + }, + } + targetDonPeers = []peer{ + { + PeerID: "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", + Signer: "0x3F82750353Ea7a051ec9bA011BC628284f9a5327", + }, + { + PeerID: "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", + Signer: "0xc23545876A208AA0443B1b8d552c7be4FF4b53F0", + }, + { + PeerID: "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", + Signer: "0x82601Fa43d8B1dC1d4eB640451aC86a7CDA37011", + }, + { + PeerID: "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", + Signer: "0x1a684B3d8f917fe496b7B1A8b29EDDAED64F649f", + }, + } +) + +type deployAndInitializeCapabilitiesRegistryCommand struct{} + +func NewDeployAndInitializeCapabilitiesRegistryCommand() *deployAndInitializeCapabilitiesRegistryCommand { + return &deployAndInitializeCapabilitiesRegistryCommand{} +} + +func (c *deployAndInitializeCapabilitiesRegistryCommand) Name() string { + return "deploy-and-initialize-capabilities-registry" +} + +func peerIDToB(peerID string) ([32]byte, error) { + var peerIDB ragetypes.PeerID + err := peerIDB.UnmarshalText([]byte(peerID)) + if err != nil { + return [32]byte{}, err + } + + return peerIDB, nil +} + +func peers(ps []peer) ([][32]byte, error) { + out := [][32]byte{} + for _, p := range ps { + b, err := peerIDToB(p.PeerID) + if err != nil { + return nil, err + } + + out = append(out, b) + } + + return out, nil +} + +func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error) { + peerIDB, err := peerIDToB(p.PeerID) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert peerID: %w", err) + } + + sig := strings.TrimPrefix(p.Signer, "0x") + signerB, err := hex.DecodeString(sig) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert signer: %w", err) + } + + var sigb [32]byte + copy(sigb[:], signerB) + + return kcr.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + P2pId: peerIDB, + Signer: sigb, + }, nil +} + +// Run expects the following environment variables to be set: +// +// 1. Deploys the CapabilitiesRegistry contract +// 2. Configures it with a hardcode DON setup, as used by our staging environment. +func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { + ctx := context.Background() + + fs := flag.NewFlagSet(c.Name(), flag.ExitOnError) + // create flags for all of the env vars then set the env vars to normalize the interface + // this is a bit of a hack but it's the easiest way to make this work + ethUrl := fs.String("ethurl", "", "URL of the Ethereum node") + chainID := fs.Int64("chainid", 11155111, "chain ID of the Ethereum network to deploy to") + accountKey := fs.String("accountkey", "", "private key of the account to deploy from") + capabilityRegistryAddress := fs.String("craddress", "", "address of the capability registry") + + err := fs.Parse(args) + if err != nil || + *ethUrl == "" || ethUrl == nil || + *chainID == 0 || chainID == nil || + *accountKey == "" || accountKey == nil { + fs.Usage() + os.Exit(1) + } + + os.Setenv("ETH_URL", *ethUrl) + os.Setenv("ETH_CHAIN_ID", fmt.Sprintf("%d", *chainID)) + os.Setenv("ACCOUNT_KEY", *accountKey) + + env := helpers.SetupEnv(false) + + var reg *kcr.CapabilitiesRegistry + if *capabilityRegistryAddress == "" { + reg = deployCapabilitiesRegistry(env) + } else { + addr := common.HexToAddress(*capabilityRegistryAddress) + r, innerErr := kcr.NewCapabilitiesRegistry(addr, env.Ec) + if err != nil { + panic(innerErr) + } + + reg = r + } + + streamsTrigger := kcr.CapabilitiesRegistryCapability{ + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: uint8(0), // trigger + } + sid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) + if err != nil { + panic(err) + } + + writeChain := kcr.CapabilitiesRegistryCapability{ + LabelledName: "write_ethereum-testnet-sepolia", + Version: "1.0.0", + CapabilityType: uint8(3), // target + } + wid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) + if err != nil { + log.Printf("failed to call GetHashedCapabilityId: %s", err) + } + + ocr := kcr.CapabilitiesRegistryCapability{ + LabelledName: "offchain_reporting", + Version: "1.0.0", + CapabilityType: uint8(2), // consensus + } + ocrid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, ocr.LabelledName, ocr.Version) + if err != nil { + log.Printf("failed to call GetHashedCapabilityId: %s", err) + } + + tx, err := reg.AddCapabilities(env.Owner, []kcr.CapabilitiesRegistryCapability{ + streamsTrigger, + writeChain, + ocr, + }) + if err != nil { + log.Printf("failed to call AddCapabilities: %s", err) + } + + helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID) + + tx, err = reg.AddNodeOperators(env.Owner, []kcr.CapabilitiesRegistryNodeOperator{ + { + Admin: env.Owner.From, + Name: "STAGING_NODE_OPERATOR", + }, + }) + if err != nil { + log.Printf("failed to AddNodeOperators: %s", err) + } + + receipt := helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID) + + recLog, err := reg.ParseNodeOperatorAdded(*receipt.Logs[0]) + if err != nil { + panic(err) + } + + nopID := recLog.NodeOperatorId + nodes := []kcr.CapabilitiesRegistryNodeParams{} + for _, wfPeer := range workflowDonPeers { + n, innerErr := peerToNode(nopID, wfPeer) + if innerErr != nil { + panic(innerErr) + } + + n.HashedCapabilityIds = [][32]byte{ocrid} + 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) + } + + tx, err = reg.AddNodes(env.Owner, nodes) + if err != nil { + log.Printf("failed to AddNodes: %s", err) + } + + helpers.ConfirmTXMined(ctx, env.Ec, tx, env.ChainID) + + // workflow DON + ps, err := peers(workflowDonPeers) + if err != nil { + panic(err) + } + + cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: ocrid, + }, + } + _, err = reg.AddDON(env.Owner, ps, cfgs, false, true, 2) + if err != nil { + log.Printf("workflowDON: failed to AddDON: %s", err) + } + + // trigger DON + ps, err = peers(triggerDonPeers) + if err != nil { + panic(err) + } + + config := &remotetypes.RemoteTriggerConfig{ + RegistrationRefreshMs: 20000, + RegistrationExpiryMs: 60000, + // 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) + } + + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: wid, + }, + } + _, 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 { + _, tx, contract, err := kcr.DeployCapabilitiesRegistry(env.Owner, env.Ec) + if err != nil { + panic(err) + } + + addr := helpers.ConfirmContractDeployed(context.Background(), env.Ec, tx, env.ChainID) + fmt.Printf("CapabilitiesRegistry address: %s", addr) + return contract +} diff --git a/core/scripts/setup_testdb.sh b/core/scripts/setup_testdb.sh index 534c980feb..85aa5812e2 100755 --- a/core/scripts/setup_testdb.sh +++ b/core/scripts/setup_testdb.sh @@ -57,7 +57,7 @@ echo $db_url repo=$(git rev-parse --show-toplevel) pushd $repo export $db_url -make testdb || exit_error "Failed to create test database" +make testdb-force || exit_error "Failed to create test database" popd # Set the database URL in the .dbenv file diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index 7b47a2f852..1fabd20b60 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -960,6 +960,10 @@ func main() { fastestResponseTimeInSeconds, err := consumer.SFastestResponseTimeInBlocks(nil) helpers.PanicErr(err) fmt.Println("Fastest Response Time In Seconds: ", fastestResponseTimeInSeconds) + p90FulfillmentBlockTime, p95FulfillmentBlockTime, err := v2plusscripts.CalculateFulfillmentResponseTimePercentiles(e, consumer) + helpers.PanicErr(err) + fmt.Println("P90 Fulfillment Block Time: ", p90FulfillmentBlockTime) + fmt.Println("P95 Fulfillment Block Time: ", p95FulfillmentBlockTime) case "eoa-load-test-reset-metrics": request := flag.NewFlagSet("eoa-load-test-reset-metrics", flag.ExitOnError) consumerAddress := request.String("consumer-address", "", "consumer address") diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go index 3d51160581..091b324443 100644 --- a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go +++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go @@ -6,6 +6,8 @@ import ( "fmt" "math/big" + "github.com/montanaflynn/stats" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -316,3 +318,40 @@ func EoaV2PlusLoadTestConsumerWithMetricsDeploy(e helpers.Environment, consumerC helpers.PanicErr(err) return helpers.ConfirmContractDeployed(context.Background(), e.Ec, tx, e.ChainID) } + +func CalculateFulfillmentResponseTimePercentiles(e helpers.Environment, consumer *vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetrics) (float64, float64, error) { + var responseTimesInBlocks []uint32 + for { + currentResponseTimesInBlocks, err := consumer.GetRequestBlockTimes(&bind.CallOpts{ + From: e.Owner.From, + Context: context.Background(), + }, big.NewInt(int64(len(responseTimesInBlocks))), big.NewInt(1000)) + if err != nil { + return 0, 0, err + } + if len(currentResponseTimesInBlocks) == 0 { + break + } + responseTimesInBlocks = append(responseTimesInBlocks, currentResponseTimesInBlocks...) + } + var p90FulfillmentBlockTime, p95FulfillmentBlockTime float64 + var err error + if len(responseTimesInBlocks) == 0 { + p90FulfillmentBlockTime = 0 + p95FulfillmentBlockTime = 0 + } else { + responseTimesInBlocksFloat64 := make([]float64, len(responseTimesInBlocks)) + for i, value := range responseTimesInBlocks { + responseTimesInBlocksFloat64[i] = float64(value) + } + p90FulfillmentBlockTime, err = stats.Percentile(responseTimesInBlocksFloat64, 90) + if err != nil { + return 0, 0, err + } + p95FulfillmentBlockTime, err = stats.Percentile(responseTimesInBlocksFloat64, 95) + if err != nil { + return 0, 0, err + } + } + return p90FulfillmentBlockTime, p95FulfillmentBlockTime, nil +} diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 076c93009a..c885a3b210 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -17,6 +17,7 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" + pkgcapabilities "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -205,6 +206,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { } var externalPeerWrapper p2ptypes.PeerWrapper + var getLocalNode func(ctx context.Context) (pkgcapabilities.Node, error) if cfg.Capabilities().Peering().Enabled() { externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) signer := externalPeer @@ -217,10 +219,29 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("failed to create hardcoded Don network setup: %w", err) } - // NOTE: RegistrySyncer will depend on a Relayer when fully implemented dispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) - registrySyncer := capabilities.NewRegistrySyncer(externalPeerWrapper, opts.CapabilitiesRegistry, dispatcher, globalLogger, networkSetup) + rid := cfg.Capabilities().ExternalRegistry().RelayID() + registryAddress := cfg.Capabilities().ExternalRegistry().Address() + relayer, err := relayerChainInterops.Get(rid) + if err != nil { + return nil, fmt.Errorf("could not fetch relayer %s configured for capabilities registry: %w", rid, err) + } + + registrySyncer, err := capabilities.NewRegistrySyncer( + externalPeerWrapper, + opts.CapabilitiesRegistry, + dispatcher, + globalLogger, + networkSetup, + relayer, + registryAddress, + ) + if err != nil { + return nil, fmt.Errorf("could not configure syncer: %w", err) + } + + getLocalNode = registrySyncer.LocalNode srvcs = append(srvcs, dispatcher, registrySyncer) } @@ -412,14 +433,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { globalLogger, opts.CapabilitiesRegistry, workflowORM, - func() *p2ptypes.PeerID { - if externalPeerWrapper == nil { - return nil - } - - peerID := externalPeerWrapper.GetPeer().ID() - return &peerID - }, + getLocalNode, ) // Flux monitor requires ethereum just to boot, silence errors with a null delegate diff --git a/core/services/chainlink/config_capabilities.go b/core/services/chainlink/config_capabilities.go index d432d31ad1..c438ca249d 100644 --- a/core/services/chainlink/config_capabilities.go +++ b/core/services/chainlink/config_capabilities.go @@ -3,6 +3,8 @@ package chainlink import ( "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" + + "github.com/smartcontractkit/chainlink-common/pkg/types" ) var _ config.Capabilities = (*capabilitiesConfig)(nil) @@ -14,3 +16,29 @@ type capabilitiesConfig struct { func (c *capabilitiesConfig) Peering() config.P2P { return &p2p{c: c.c.Peering} } + +func (c *capabilitiesConfig) ExternalRegistry() config.CapabilitiesExternalRegistry { + return &capabilitiesExternalRegistry{ + c: c.c.ExternalRegistry, + } +} + +type capabilitiesExternalRegistry struct { + c toml.ExternalRegistry +} + +func (c *capabilitiesExternalRegistry) RelayID() types.RelayID { + return types.NewRelayID(c.NetworkID(), c.ChainID()) +} + +func (c *capabilitiesExternalRegistry) NetworkID() string { + return *c.c.NetworkID +} + +func (c *capabilitiesExternalRegistry) ChainID() string { + return *c.c.ChainID +} + +func (c *capabilitiesExternalRegistry) Address() string { + return *c.c.Address +} diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index d23af39090..08c3a18aca 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -445,6 +445,11 @@ func TestConfig_Marshal(t *testing.T) { ListenAddresses: &[]string{"foo", "bar"}, }, }, + ExternalRegistry: toml.ExternalRegistry{ + Address: ptr(""), + ChainID: ptr("1"), + NetworkID: ptr("evm"), + }, } full.Keeper = toml.Keeper{ DefaultTransactionQueueDepth: ptr[uint32](17), @@ -1284,11 +1289,10 @@ func TestConfig_Validate(t *testing.T) { - WSURL: missing: required for primary nodes - HTTPURL: missing: required for all nodes - 1.HTTPURL: missing: required for all nodes - - 1: 10 errors: + - 1: 9 errors: - ChainType: invalid value (Foo): must not be set with this chain id - Nodes: missing: must have at least one node - ChainType: invalid value (Foo): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted - - HeadTracker.HistoryDepth: invalid value (30): must be equal to or greater than FinalityDepth - GasEstimator.BumpThreshold: invalid value (0): cannot be 0 if auto-purge feature is enabled for Foo - Transactions.AutoPurge.Threshold: missing: needs to be set if auto-purge feature is enabled for Foo - Transactions.AutoPurge.MinAttempts: missing: needs to be set if auto-purge feature is enabled for Foo diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index c2baa1edcd..c4fbd26861 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -18,17 +18,17 @@ import ( solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" + evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/plugins" - - evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" ) func TestCoreRelayerChainInteroperators(t *testing.T) { @@ -217,10 +217,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedEVMChainCnt: 2, expectedEVMNodeCnt: 3, expectedEVMRelayerIds: []types.RelayID{ - {Network: types.NetworkEVM, ChainID: evmChainID1.String()}, - {Network: types.NetworkEVM, ChainID: evmChainID2.String()}, + {Network: relay.NetworkEVM, ChainID: evmChainID1.String()}, + {Network: relay.NetworkEVM, ChainID: evmChainID2.String()}, }, - expectedRelayerNetworks: map[string]struct{}{types.NetworkEVM: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}}, }, {name: "2 solana chain with 2 node", @@ -233,10 +233,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedSolanaChainCnt: 2, expectedSolanaNodeCnt: 2, expectedSolanaRelayerIds: []types.RelayID{ - {Network: types.NetworkSolana, ChainID: solanaChainID1}, - {Network: types.NetworkSolana, ChainID: solanaChainID2}, + {Network: relay.NetworkSolana, ChainID: solanaChainID1}, + {Network: relay.NetworkSolana, ChainID: solanaChainID2}, }, - expectedRelayerNetworks: map[string]struct{}{types.NetworkSolana: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkSolana: {}}, }, {name: "2 starknet chain with 4 nodes", @@ -249,10 +249,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedStarknetChainCnt: 2, expectedStarknetNodeCnt: 4, expectedStarknetRelayerIds: []types.RelayID{ - {Network: types.NetworkStarkNet, ChainID: starknetChainID1}, - {Network: types.NetworkStarkNet, ChainID: starknetChainID2}, + {Network: relay.NetworkStarkNet, ChainID: starknetChainID1}, + {Network: relay.NetworkStarkNet, ChainID: starknetChainID2}, }, - expectedRelayerNetworks: map[string]struct{}{types.NetworkStarkNet: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkStarkNet: {}}, }, { @@ -267,10 +267,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedCosmosChainCnt: 2, expectedCosmosNodeCnt: 2, expectedCosmosRelayerIds: []types.RelayID{ - {Network: types.NetworkCosmos, ChainID: cosmosChainID1}, - {Network: types.NetworkCosmos, ChainID: cosmosChainID2}, + {Network: relay.NetworkCosmos, ChainID: cosmosChainID1}, + {Network: relay.NetworkCosmos, ChainID: cosmosChainID2}, }, - expectedRelayerNetworks: map[string]struct{}{types.NetworkCosmos: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkCosmos: {}}, }, {name: "all chains", @@ -299,32 +299,32 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedEVMChainCnt: 2, expectedEVMNodeCnt: 3, expectedEVMRelayerIds: []types.RelayID{ - {Network: types.NetworkEVM, ChainID: evmChainID1.String()}, - {Network: types.NetworkEVM, ChainID: evmChainID2.String()}, + {Network: relay.NetworkEVM, ChainID: evmChainID1.String()}, + {Network: relay.NetworkEVM, ChainID: evmChainID2.String()}, }, expectedSolanaChainCnt: 2, expectedSolanaNodeCnt: 2, expectedSolanaRelayerIds: []types.RelayID{ - {Network: types.NetworkSolana, ChainID: solanaChainID1}, - {Network: types.NetworkSolana, ChainID: solanaChainID2}, + {Network: relay.NetworkSolana, ChainID: solanaChainID1}, + {Network: relay.NetworkSolana, ChainID: solanaChainID2}, }, expectedStarknetChainCnt: 2, expectedStarknetNodeCnt: 4, expectedStarknetRelayerIds: []types.RelayID{ - {Network: types.NetworkStarkNet, ChainID: starknetChainID1}, - {Network: types.NetworkStarkNet, ChainID: starknetChainID2}, + {Network: relay.NetworkStarkNet, ChainID: starknetChainID1}, + {Network: relay.NetworkStarkNet, ChainID: starknetChainID2}, }, expectedCosmosChainCnt: 2, expectedCosmosNodeCnt: 2, expectedCosmosRelayerIds: []types.RelayID{ - {Network: types.NetworkCosmos, ChainID: cosmosChainID1}, - {Network: types.NetworkCosmos, ChainID: cosmosChainID2}, + {Network: relay.NetworkCosmos, ChainID: cosmosChainID1}, + {Network: relay.NetworkCosmos, ChainID: cosmosChainID2}, }, - expectedRelayerNetworks: map[string]struct{}{types.NetworkEVM: {}, types.NetworkCosmos: {}, types.NetworkSolana: {}, types.NetworkStarkNet: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}, relay.NetworkCosmos: {}, relay.NetworkSolana: {}, relay.NetworkStarkNet: {}}, }, } for _, tt := range tests { @@ -357,17 +357,20 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { } gotRelayerNetworks := make(map[string]struct{}) - for relayNetwork := range types.SupportedRelays { + for relayNetwork := range relay.SupportedNetworks { var expectedChainCnt, expectedNodeCnt int switch relayNetwork { - case types.NetworkEVM: + case relay.NetworkEVM: expectedChainCnt, expectedNodeCnt = tt.expectedEVMChainCnt, tt.expectedEVMNodeCnt - case types.NetworkCosmos: + case relay.NetworkCosmos: expectedChainCnt, expectedNodeCnt = tt.expectedCosmosChainCnt, tt.expectedCosmosNodeCnt - case types.NetworkSolana: + case relay.NetworkSolana: expectedChainCnt, expectedNodeCnt = tt.expectedSolanaChainCnt, tt.expectedSolanaNodeCnt - case types.NetworkStarkNet: + case relay.NetworkStarkNet: expectedChainCnt, expectedNodeCnt = tt.expectedStarknetChainCnt, tt.expectedStarknetNodeCnt + case relay.NetworkAptos: + t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") + default: require.Fail(t, "untested relay network", relayNetwork) } @@ -379,16 +382,16 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { } // check legacy chains for those that haven't migrated fully to the loop relayer interface - if relayNetwork == types.NetworkEVM { - _, wantEVM := tt.expectedRelayerNetworks[types.NetworkEVM] + if relayNetwork == relay.NetworkEVM { + _, wantEVM := tt.expectedRelayerNetworks[relay.NetworkEVM] if wantEVM { assert.Len(t, cr.LegacyEVMChains().Slice(), expectedChainCnt) } else { assert.Nil(t, cr.LegacyEVMChains()) } } - if relayNetwork == types.NetworkCosmos { - _, wantCosmos := tt.expectedRelayerNetworks[types.NetworkCosmos] + if relayNetwork == relay.NetworkCosmos { + _, wantCosmos := tt.expectedRelayerNetworks[relay.NetworkCosmos] if wantCosmos { assert.Len(t, cr.LegacyCosmosChains().Slice(), expectedChainCnt) } else { @@ -419,13 +422,13 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { assert.NoError(t, err) assert.Equal(t, wantId.ChainID, stat.ID) // check legacy chains for evm and cosmos - if wantId.Network == types.NetworkEVM { + if wantId.Network == relay.NetworkEVM { c, err := cr.LegacyEVMChains().Get(wantId.ChainID) assert.NoError(t, err) assert.NotNil(t, c) assert.Equal(t, wantId.ChainID, c.ID().String()) } - if wantId.Network == types.NetworkCosmos { + if wantId.Network == relay.NetworkCosmos { c, err := cr.LegacyCosmosChains().Get(wantId.ChainID) assert.NoError(t, err) assert.NotNil(t, c) @@ -434,7 +437,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { } } - expectedMissing := types.RelayID{Network: types.NetworkCosmos, ChainID: "not a chain id"} + expectedMissing := types.RelayID{Network: relay.NetworkCosmos, ChainID: "not a chain id"} unwanted, err := cr.Get(expectedMissing) assert.Nil(t, unwanted) assert.ErrorIs(t, err, chainlink.ErrNoSuchRelayer) diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index bcdb08b802..528678652f 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -25,6 +25,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + corerelay "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/plugins" @@ -64,7 +65,7 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m } legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(evmRelayExtenders) for _, ext := range evmRelayExtenders.Slice() { - relayID := types.RelayID{Network: types.NetworkEVM, ChainID: ext.Chain().ID().String()} + relayID := types.RelayID{Network: corerelay.NetworkEVM, ChainID: ext.Chain().ID().String()} chain, err2 := legacyChains.Get(relayID.ChainID) if err2 != nil { return nil, err2 @@ -105,7 +106,7 @@ func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solcfg.TOMLConf unique := make(map[string]struct{}) // create one relayer per chain id for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: types.NetworkSolana, ChainID: *chainCfg.ChainID} + relayID := types.RelayID{Network: corerelay.NetworkSolana, ChainID: *chainCfg.ChainID} _, alreadyExists := unique[relayID.Name()] if alreadyExists { return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) @@ -178,7 +179,7 @@ func (r *RelayerFactory) NewStarkNet(ks keystore.StarkNet, chainCfgs config.TOML unique := make(map[string]struct{}) // create one relayer per chain id for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: types.NetworkStarkNet, ChainID: *chainCfg.ChainID} + relayID := types.RelayID{Network: corerelay.NetworkStarkNet, ChainID: *chainCfg.ChainID} _, alreadyExists := unique[relayID.Name()] if alreadyExists { return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) @@ -273,7 +274,7 @@ func (r *RelayerFactory) NewCosmos(config CosmosFactoryConfig) (map[types.RelayI // create one relayer per chain id for _, chainCfg := range config.TOMLConfigs { - relayID := types.RelayID{Network: types.NetworkCosmos, ChainID: *chainCfg.ChainID} + relayID := types.RelayID{Network: corerelay.NetworkCosmos, ChainID: *chainCfg.ChainID} lggr := cosmosLggr.Named(relayID.ChainID) diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index e8c2faaa45..d5211a5157 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -249,3 +249,8 @@ DefaultBootstrappers = [] DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] + +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 645535cc1c..6a0bbe8688 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -260,6 +260,11 @@ DeltaDial = '1m0s' DeltaReconcile = '2s' ListenAddresses = ['foo', 'bar'] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' Enabled = false diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 3807452dee..7ca4311764 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -250,6 +250,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 29a72f5a2b..d3eea4b29d 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -278,7 +278,7 @@ func (s *service) UpdateManager(ctx context.Context, mgr FeedsManager) error { } if err := s.restartConnection(ctx, mgr); err != nil { - s.lggr.Errorf("could not restart FMS connection: %w", err) + s.lggr.Errorf("could not restart FMS connection: %v", err) } return nil @@ -349,7 +349,7 @@ func (s *service) CreateChainConfig(ctx context.Context, cfg ChainConfig) (int64 } if err := s.SyncNodeInfo(ctx, mgr.ID); err != nil { - s.lggr.Infof("FMS: Unable to sync node info: %w", err) + s.lggr.Infof("FMS: Unable to sync node info: %v", err) } return id, nil @@ -373,7 +373,7 @@ func (s *service) DeleteChainConfig(ctx context.Context, id int64) (int64, error } if err := s.SyncNodeInfo(ctx, mgr.ID); err != nil { - s.lggr.Infof("FMS: Unable to sync node info: %w", err) + s.lggr.Infof("FMS: Unable to sync node info: %v", err) } return id, nil @@ -414,7 +414,7 @@ func (s *service) UpdateChainConfig(ctx context.Context, cfg ChainConfig) (int64 } if err := s.SyncNodeInfo(ctx, ccfg.FeedsManagerID); err != nil { - s.lggr.Infof("FMS: Unable to sync node info: %w", err) + s.lggr.Infof("FMS: Unable to sync node info: %v", err) } return id, nil @@ -468,7 +468,7 @@ func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, er } if err = s.observeJobProposalCounts(ctx); err != nil { - logger.Errorw("Failed to push metrics for job proposal deletion", err) + logger.Errorw("Failed to push metrics for job proposal deletion", "err", err) } return proposal.ID, nil @@ -520,7 +520,7 @@ func (s *service) RevokeJob(ctx context.Context, args *RevokeJobArgs) (int64, er ) if err = s.observeJobProposalCounts(ctx); err != nil { - logger.Errorw("Failed to push metrics for revoke job", err) + logger.Errorw("Failed to push metrics for revoke job", "err", err) } return proposal.ID, nil @@ -634,7 +634,7 @@ func (s *service) ProposeJob(ctx context.Context, args *ProposeJobArgs) (int64, } if err = s.observeJobProposalCounts(ctx); err != nil { - logger.Errorw("Failed to push metrics for propose job", err) + logger.Errorw("Failed to push metrics for propose job", "err", err) } return id, nil @@ -706,7 +706,7 @@ func (s *service) RejectSpec(ctx context.Context, id int64) error { } if err = s.observeJobProposalCounts(ctx); err != nil { - logger.Errorw("Failed to push metrics for job rejection", err) + logger.Errorw("Failed to push metrics for job rejection", "err", err) } return nil @@ -885,7 +885,7 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { } if err = s.observeJobProposalCounts(ctx); err != nil { - logger.Errorw("Failed to push metrics for job approval", err) + logger.Errorw("Failed to push metrics for job approval", "err", err) } return nil @@ -975,7 +975,7 @@ func (s *service) CancelSpec(ctx context.Context, id int64) error { } if err = s.observeJobProposalCounts(ctx); err != nil { - logger.Errorw("Failed to push metrics for job cancellation", err) + logger.Errorw("Failed to push metrics for job cancellation", "err", err) } return nil @@ -1191,7 +1191,7 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error case job.FluxMonitor: js, err = fluxmonitorv2.ValidatedFluxMonitorSpec(s.jobCfg, spec) case job.Workflow: - js, err = workflows.ValidatedWorkflowSpec(spec) + js, err = workflows.ValidatedWorkflowJobSpec(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 bc1f1afa44..8c2f60bd63 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -652,37 +652,7 @@ func Test_Service_ProposeJob(t *testing.T) { httpTimeout = *commonconfig.MustNewDuration(1 * time.Second) // variables for workflow spec - wfID = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - wfOwner = "00000000000000000000000000000000000000aa" - wfName = "myworkflow" // len 10 - specYaml = ` -triggers: - - id: "a-trigger@1.0.0" - config: {} - -actions: - - id: "an-action@1.0.0" - ref: "an-action" - config: {} - inputs: - trigger_output: $(trigger.outputs) - -consensus: - - id: "a-consensus@1.0.0" - ref: "a-consensus" - config: {} - inputs: - trigger_output: $(trigger.outputs) - an-action_output: $(an-action.outputs) - -targets: - - id: "a-target@1.0.0" - config: {} - ref: "a-target" - inputs: - consensus_output: $(a-consensus.outputs) -` - wfSpec = testspecs.GenerateWorkflowSpec(wfID, wfOwner, wfName, specYaml).Toml() + wfJobSpec = testspecs.DefaultWorkflowJobSpec(t) proposalIDWF = int64(11) jobProposalSpecIdWF = int64(101) jobIDWF = int32(1001) @@ -690,7 +660,7 @@ targets: argsWF = &feeds.ProposeJobArgs{ FeedsManagerID: 1, RemoteUUID: remoteUUIDWF, - Spec: wfSpec, + Spec: wfJobSpec.Toml(), Version: 1, } jpWF = feeds.JobProposal{ @@ -707,14 +677,14 @@ targets: Status: feeds.JobProposalStatusPending, } proposalSpecWF = feeds.JobProposalSpec{ - Definition: wfSpec, + Definition: wfJobSpec.Toml(), Status: feeds.SpecStatusPending, Version: 1, JobProposalID: proposalIDWF, } autoApprovableProposalSpecWF = feeds.JobProposalSpec{ ID: jobProposalSpecIdWF, - Definition: wfSpec, + Definition: wfJobSpec.Toml(), Status: feeds.SpecStatusPending, Version: 1, JobProposalID: proposalIDWF, @@ -755,7 +725,11 @@ targets: mock.Anything, mock.Anything, mock.MatchedBy(func(j *job.Job) bool { - return j.WorkflowSpec.WorkflowOwner == wfOwner + match := j.WorkflowSpec.Workflow == wfJobSpec.Job().WorkflowSpec.Workflow + if !match { + t.Logf("got wf spec %s want %s", j.WorkflowSpec.Workflow, wfJobSpec.Job().WorkflowSpec.Workflow) + } + return match }), ). Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). @@ -807,7 +781,11 @@ targets: mock.Anything, mock.Anything, mock.MatchedBy(func(j *job.Job) bool { - return j.WorkflowSpec.WorkflowOwner == wfOwner + match := j.WorkflowSpec.Workflow == wfJobSpec.Job().WorkflowSpec.Workflow + if !match { + t.Logf("got wf spec %s want %s", j.WorkflowSpec.Workflow, wfJobSpec.Job().WorkflowSpec.Workflow) + } + return match }), ). Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). @@ -855,7 +833,11 @@ targets: mock.Anything, mock.Anything, mock.MatchedBy(func(j *job.Job) bool { - return j.WorkflowSpec.WorkflowOwner == wfOwner + match := j.WorkflowSpec.Workflow == wfJobSpec.Job().WorkflowSpec.Workflow + if !match { + t.Logf("got wf spec %s want %s", j.WorkflowSpec.Workflow, wfJobSpec.Job().WorkflowSpec.Workflow) + } + return match }), ). Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). diff --git a/core/services/gateway/handlers/functions/allowlist/allowlist.go b/core/services/gateway/handlers/functions/allowlist/allowlist.go index 2a27f51471..d180195865 100644 --- a/core/services/gateway/handlers/functions/allowlist/allowlist.go +++ b/core/services/gateway/handlers/functions/allowlist/allowlist.go @@ -237,12 +237,12 @@ func (a *onchainAllowlist) updateFromContractV1(ctx context.Context, blockNum *b err = a.orm.PurgeAllowedSenders(ctx) if err != nil { - a.lggr.Errorf("failed to purge allowedSenderList: %w", err) + a.lggr.Errorf("failed to purge allowedSenderList: %v", err) } err = a.orm.CreateAllowedSenders(ctx, allowedSenderList) if err != nil { - a.lggr.Errorf("failed to update stored allowedSenderList: %w", err) + a.lggr.Errorf("failed to update stored allowedSenderList: %v", err) } a.update(allowedSenderList) @@ -343,7 +343,7 @@ func (a *onchainAllowlist) updateAllowedSendersBatch( // persist each batch to the underalying orm layer err = a.orm.CreateAllowedSenders(ctx, allowedSendersBatch) if err != nil { - a.lggr.Errorf("failed to update stored allowedSenderList: %w", err) + a.lggr.Errorf("failed to update stored allowedSenderList: %v", err) } return nil } @@ -380,7 +380,7 @@ func (a *onchainAllowlist) syncBlockedSenders(ctx context.Context, tosContract * err = a.orm.DeleteAllowedSenders(ctx, blockedSendersBatch) if err != nil { - a.lggr.Errorf("failed to delete blocked address from allowed list in storage: %w", err) + a.lggr.Errorf("failed to delete blocked address from allowed list in storage: %v", err) } } throttleTicker.Stop() @@ -403,7 +403,7 @@ func (a *onchainAllowlist) loadStoredAllowedSenderList(ctx context.Context) { for { asBatch, err := a.orm.GetAllowedSenders(ctx, offset, a.config.StoredAllowlistBatchSize) if err != nil { - a.lggr.Errorf("failed to get stored allowed senders: %w", err) + a.lggr.Errorf("failed to get stored allowed senders: %v", err) break } diff --git a/core/services/gateway/handlers/functions/subscriptions/subscriptions.go b/core/services/gateway/handlers/functions/subscriptions/subscriptions.go index d481ecf12e..c2b2835099 100644 --- a/core/services/gateway/handlers/functions/subscriptions/subscriptions.go +++ b/core/services/gateway/handlers/functions/subscriptions/subscriptions.go @@ -210,7 +210,7 @@ func (s *onchainSubscriptions) querySubscriptionsRange(ctx context.Context, bloc SubscriptionID: subscriptionId, IFunctionsSubscriptionsSubscription: subscription, }); err != nil { - s.lggr.Errorf("unexpected error updating subscription in the db: %w", err) + s.lggr.Errorf("unexpected error updating subscription in the db: %v", err) } } } diff --git a/core/services/gateway/network/wsclient.go b/core/services/gateway/network/wsclient.go index bc248d202a..436ff01a92 100644 --- a/core/services/gateway/network/wsclient.go +++ b/core/services/gateway/network/wsclient.go @@ -51,7 +51,7 @@ func (c *webSocketClient) Connect(ctx context.Context, url *url.URL) (*websocket conn, resp, err := c.dialer.DialContext(ctx, url.String(), hdr) if err != nil { - c.lggr.Errorf("WebSocketClient: couldn't connect to %s: %w", url.String(), err) + c.lggr.Errorf("WebSocketClient: couldn't connect to %s: %v", url.String(), err) c.tryCloseConn(conn) return nil, err } @@ -71,13 +71,13 @@ func (c *webSocketClient) Connect(ctx context.Context, url *url.URL) (*websocket response, err := c.initiator.ChallengeResponse(url, challenge) if err != nil { - c.lggr.Errorf("WebSocketClient: couldn't generate challenge response", err) + c.lggr.Error("WebSocketClient: couldn't generate challenge response; error: ", err) c.tryCloseConn(conn) return nil, err } if err = conn.WriteMessage(websocket.BinaryMessage, response); err != nil { - c.lggr.Errorf("WebSocketClient: couldn't send challenge response", err) + c.lggr.Error("WebSocketClient: couldn't send challenge response; error: ", err) c.tryCloseConn(conn) return nil, err } @@ -88,7 +88,7 @@ func (c *webSocketClient) tryCloseConn(conn *websocket.Conn) { if conn != nil { err := conn.Close() if err != nil { - c.lggr.Errorf("WebSocketClient: error closing connection %w", err) + c.lggr.Errorf("WebSocketClient: error closing connection %v", err) } } } diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index e051d1fb18..976847da45 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -42,6 +43,7 @@ import ( ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" @@ -949,7 +951,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { t.Run("test ETH key validation", func(t *testing.T) { ctx := testutils.Context(t) - jb.OCR2OracleSpec.Relay = types.NetworkEVM + jb.OCR2OracleSpec.Relay = relay.NetworkEVM err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no EVM key matching: \"bad key\"") @@ -960,7 +962,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { t.Run("test Cosmos key validation", func(t *testing.T) { ctx := testutils.Context(t) - jb.OCR2OracleSpec.Relay = types.NetworkCosmos + jb.OCR2OracleSpec.Relay = relay.NetworkCosmos err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no Cosmos key matching: \"bad key\"") @@ -972,7 +974,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { t.Run("test Solana key validation", func(t *testing.T) { ctx := testutils.Context(t) - jb.OCR2OracleSpec.Relay = types.NetworkSolana + jb.OCR2OracleSpec.Relay = relay.NetworkSolana err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no Solana key matching: \"bad key\"") @@ -985,7 +987,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { t.Run("test Starknet key validation", func(t *testing.T) { ctx := testutils.Context(t) - jb.OCR2OracleSpec.Relay = types.NetworkStarkNet + jb.OCR2OracleSpec.Relay = relay.NetworkStarkNet err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no Starknet key matching: \"bad key\"") @@ -1806,12 +1808,15 @@ func Test_CountPipelineRunsByJobID(t *testing.T) { } func Test_ORM_FindJobByWorkflow(t *testing.T) { + var addr1 = "0x0123456789012345678901234567890123456789" + var addr2 = "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" + t.Parallel() type fields struct { ds sqlutil.DataSource } type args struct { - spec job.WorkflowSpec - before func(t *testing.T, o job.ORM, s job.WorkflowSpec) int32 + spec *job.WorkflowSpec + before func(t *testing.T, o job.ORM, s *job.WorkflowSpec) int32 } tests := []struct { name string @@ -1819,6 +1824,7 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { args args wantErr bool }{ + { name: "wf not job found", fields: fields{ @@ -1826,28 +1832,23 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { }, args: args{ // before is nil, so no job is inserted - spec: job.WorkflowSpec{ - ID: 1, - WorkflowID: "workflow 1", - Workflow: "abcd", - WorkflowOwner: "me", - WorkflowName: "myworkflow", + spec: &job.WorkflowSpec{ + ID: 1, + Workflow: pkgworkflows.WFYamlSpec(t, "workflow00", addr1), }, }, wantErr: true, }, + { name: "wf job found", fields: fields{ ds: pgtest.NewSqlxDB(t), }, args: args{ - spec: job.WorkflowSpec{ - ID: 1, - WorkflowID: "workflow 2", - Workflow: "anything", - WorkflowOwner: "me", - WorkflowName: "myworkflow", + spec: &job.WorkflowSpec{ + ID: 1, + Workflow: pkgworkflows.WFYamlSpec(t, "workflow01", addr1), }, before: mustInsertWFJob, }, @@ -1860,16 +1861,15 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { ds: pgtest.NewSqlxDB(t), }, args: args{ - spec: job.WorkflowSpec{ - ID: 1, - WorkflowID: "workflow 3", - Workflow: "anything", - WorkflowOwner: "me", - WorkflowName: "wf3", + spec: &job.WorkflowSpec{ + ID: 1, + Workflow: pkgworkflows.WFYamlSpec(t, "workflow02", addr1), }, - before: func(t *testing.T, o job.ORM, s job.WorkflowSpec) int32 { - s.WorkflowName = "notmyworkflow" - return mustInsertWFJob(t, o, s) + before: func(t *testing.T, o job.ORM, s *job.WorkflowSpec) int32 { + var c job.WorkflowSpec + c.ID = s.ID + c.Workflow = pkgworkflows.WFYamlSpec(t, "workflow99", addr1) // insert with mismatched name + return mustInsertWFJob(t, o, &c) }, }, wantErr: true, @@ -1880,16 +1880,15 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { ds: pgtest.NewSqlxDB(t), }, args: args{ - spec: job.WorkflowSpec{ - ID: 1, - WorkflowID: "workflow 4", - Workflow: "anything", - WorkflowOwner: "me", - WorkflowName: "wf4", + spec: &job.WorkflowSpec{ + ID: 1, + Workflow: pkgworkflows.WFYamlSpec(t, "workflow03", addr1), }, - before: func(t *testing.T, o job.ORM, s job.WorkflowSpec) int32 { - s.WorkflowOwner = "not me" - return mustInsertWFJob(t, o, s) + before: func(t *testing.T, o job.ORM, s *job.WorkflowSpec) int32 { + var c job.WorkflowSpec + c.ID = s.ID + c.Workflow = pkgworkflows.WFYamlSpec(t, "workflow03", addr2) // insert with mismatched owner + return mustInsertWFJob(t, o, &c) }, }, wantErr: true, @@ -1907,7 +1906,7 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { wantJobID = tt.args.before(t, o, tt.args.spec) } ctx := testutils.Context(t) - gotJ, err := o.FindJobIDByWorkflow(ctx, tt.args.spec) + gotJ, err := o.FindJobIDByWorkflow(ctx, *tt.args.spec) if (err != nil) != tt.wantErr { t.Errorf("orm.FindJobByWorkflow() error = %v, wantErr %v", err, tt.wantErr) return @@ -1917,7 +1916,12 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { } }) } +} +func Test_ORM_FindJobByWorkflow_Multiple(t *testing.T) { + var addr1 = "0x012345678901234567890123456789012345ffff" + var addr2 = "0xabcdefabcdefabcdefabcdefabcdefabcdef0000" + t.Parallel() t.Run("multiple jobs", func(t *testing.T) { db := pgtest.NewSqlxDB(t) o := NewTestORM(t, @@ -1928,29 +1932,24 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { bridges.NewORM(db), cltest.NewKeyStore(t, db)) ctx := testutils.Context(t) + + wfYaml1 := pkgworkflows.WFYamlSpec(t, "workflow00", addr1) s1 := job.WorkflowSpec{ - WorkflowID: "workflowid", - Workflow: "anything", - WorkflowOwner: "me", - WorkflowName: "a_common_name", + Workflow: wfYaml1, } - wantJobID1 := mustInsertWFJob(t, o, s1) + wantJobID1 := mustInsertWFJob(t, o, &s1) + wfYaml2 := pkgworkflows.WFYamlSpec(t, "workflow01", addr1) s2 := job.WorkflowSpec{ - WorkflowID: "another workflowid", - Workflow: "anything", - WorkflowOwner: "me", - WorkflowName: "another workflow name", + Workflow: wfYaml2, } - wantJobID2 := mustInsertWFJob(t, o, s2) + wantJobID2 := mustInsertWFJob(t, o, &s2) + wfYaml3 := pkgworkflows.WFYamlSpec(t, "workflow00", addr2) s3 := job.WorkflowSpec{ - WorkflowID: "xworkflowid", - Workflow: "anything", - WorkflowOwner: "someone else", - WorkflowName: "a_common_name", + Workflow: wfYaml3, } - wantJobID3 := mustInsertWFJob(t, o, s3) + wantJobID3 := mustInsertWFJob(t, o, &s3) expectedIDs := []int32{wantJobID1, wantJobID2, wantJobID3} for i, s := range []job.WorkflowSpec{s1, s2, s3} { @@ -1969,20 +1968,23 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { }) } -func mustInsertWFJob(t *testing.T, orm job.ORM, s job.WorkflowSpec) int32 { +func mustInsertWFJob(t *testing.T, orm job.ORM, s *job.WorkflowSpec) int32 { t.Helper() + err := s.Validate() + require.NoError(t, err, "failed to validate spec %v", s) ctx := testutils.Context(t) - _, err := toml.Marshal(s.Workflow) - require.NoError(t, err) + _, err = toml.Marshal(s.Workflow) + require.NoError(t, err, "failed to TOML marshal workflow %v", s.Workflow) j := job.Job{ Type: job.Workflow, - WorkflowSpec: &s, + WorkflowSpec: s, ExternalJobID: uuid.New(), Name: null.StringFrom(s.WorkflowOwner + "_" + s.WorkflowName), SchemaVersion: 1, } + err = orm.CreateJob(ctx, &j) - require.NoError(t, err) + require.NoError(t, err, "failed to insert job with wf spec %v %s", s, s.Workflow) return j.ID } diff --git a/core/services/job/models.go b/core/services/job/models.go index 7b8e5f7917..5457768141 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -2,7 +2,6 @@ package job import ( "database/sql/driver" - "encoding/hex" "encoding/json" "fmt" "strconv" @@ -17,6 +16,8 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" "github.com/smartcontractkit/chainlink-common/pkg/types" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -382,7 +383,7 @@ type OCR2OracleSpec struct { func validateRelayID(id types.RelayID) error { // only the EVM has specific requirements - if id.Network == types.NetworkEVM { + if id.Network == relay.NetworkEVM { _, err := toml.ChainIDInt64(id.ChainID) if err != nil { return fmt.Errorf("invalid EVM chain id %s: %w", id.ChainID, err) @@ -850,47 +851,38 @@ type LiquidityBalancerSpec struct { } type WorkflowSpec struct { - ID int32 `toml:"-"` - // TODO it may be possible to compute the workflow id from the hash(yaml, owner, name) and remove this field - WorkflowID string `toml:"workflowId"` // globally unique identifier for the workflow, specified by the user - Workflow string `toml:"workflow"` - WorkflowOwner string `toml:"workflowOwner"` // hex string representation of 20 bytes - WorkflowName string `toml:"workflowName"` // 10 byte plain text name + ID int32 `toml:"-"` + Workflow string `toml:"workflow"` // the yaml representation of the workflow + // fields derived from the yaml spec, used for indexing the database + // note: i tried to make these private, but translating them to the database seems to require them to be public + WorkflowID string `toml:"-" db:"workflow_id"` // Derived. Do not modify. the CID of the workflow. + WorkflowOwner string `toml:"-" db:"workflow_owner"` // Derived. Do not modify. the owner of the workflow. + WorkflowName string `toml:"-" db:"workflow_name"` // Derived. Do not modify. the name of the workflow. CreatedAt time.Time `toml:"-"` UpdatedAt time.Time `toml:"-"` } var ( - ErrInvalidWorkflowID = errors.New("invalid workflow id") - ErrInvalidWorkflowOwner = errors.New("invalid workflow owner") - ErrInvalidWorkflowName = errors.New("invalid workflow name") + ErrInvalidWorkflowID = errors.New("invalid workflow id") + ErrInvalidWorkflowYAMLSpec = errors.New("invalid workflow yaml spec") ) const ( - workflowIDLen = 64 // conveniently the same length as a sha256 hash - // owner and name are constrained the onchain representation in [github.com/smartcontractkit/chainlink-common/blob/main/pkg/capabilities/consensus/ocr3/types/Metadata] - workflowOwnerLen = 40 // hex string representation of 20 bytes - workflowNameLen = 10 // plain text name + workflowIDLen = 64 // sha256 hash ) -// Validate checks the length of the workflow id, owner and name -// that latter two are constrained by the onchain representation in [github.com/smartcontractkit/chainlink-common/blob/main/pkg/capabilities/consensus/ocr3/types/Metadata] +// Validate checks the workflow spec for correctness func (w *WorkflowSpec) Validate() error { - if len(w.WorkflowID) != workflowIDLen { - return fmt.Errorf("%w: incorrect length for id %s: expected %d, got %d", ErrInvalidWorkflowID, w.WorkflowID, workflowIDLen, len(w.WorkflowID)) - } - - w.WorkflowOwner = strings.TrimPrefix(w.WorkflowOwner, "0x") - _, err := hex.DecodeString(w.WorkflowOwner) + s, err := pkgworkflows.ParseWorkflowSpecYaml(w.Workflow) if err != nil { - return fmt.Errorf("%w: expected hex encoding got %s: %w", ErrInvalidWorkflowOwner, w.WorkflowOwner, err) - } - if len(w.WorkflowOwner) != workflowOwnerLen { - return fmt.Errorf("%w: incorrect length for owner %s: expected %d, got %d", ErrInvalidWorkflowOwner, w.WorkflowOwner, workflowOwnerLen, len(w.WorkflowOwner)) + return fmt.Errorf("%w: failed to parse workflow spec %s: %w", ErrInvalidWorkflowYAMLSpec, w.Workflow, err) } + w.WorkflowOwner = strings.TrimPrefix(s.Owner, "0x") // the json schema validation ensures it is a hex string with 0x prefix, but the database does not store the prefix + w.WorkflowName = s.Name + w.WorkflowID = s.CID() - if len(w.WorkflowName) != workflowNameLen { - return fmt.Errorf("%w: incorrect length for name %s: expected %d, got %d", ErrInvalidWorkflowName, w.WorkflowName, workflowNameLen, len(w.WorkflowName)) + if len(w.WorkflowID) != workflowIDLen { + return fmt.Errorf("%w: incorrect length for id %s: expected %d, got %d", ErrInvalidWorkflowID, w.WorkflowID, workflowIDLen, len(w.WorkflowID)) } return nil diff --git a/core/services/job/models_test.go b/core/services/job/models_test.go index a5dc12bcbc..1f88bb6d38 100644 --- a/core/services/job/models_test.go +++ b/core/services/job/models_test.go @@ -10,6 +10,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -39,23 +41,23 @@ func TestOCR2OracleSpec_RelayIdentifier(t *testing.T) { { name: "evm explicitly configured", fields: fields{ - Relay: types.NetworkEVM, + Relay: relay.NetworkEVM, ChainID: "1", }, - want: types.RelayID{Network: types.NetworkEVM, ChainID: "1"}, + want: types.RelayID{Network: relay.NetworkEVM, ChainID: "1"}, }, { name: "evm implicitly configured", fields: fields{ - Relay: types.NetworkEVM, + Relay: relay.NetworkEVM, RelayConfig: map[string]any{"chainID": 1}, }, - want: types.RelayID{Network: types.NetworkEVM, ChainID: "1"}, + want: types.RelayID{Network: relay.NetworkEVM, ChainID: "1"}, }, { name: "evm implicitly configured with bad value", fields: fields{ - Relay: types.NetworkEVM, + Relay: relay.NetworkEVM, RelayConfig: map[string]any{"chainID": float32(1)}, }, want: types.RelayID{}, @@ -93,7 +95,7 @@ var ( func TestOCR2OracleSpec(t *testing.T) { val := OCR2OracleSpec{ - Relay: types.NetworkEVM, + Relay: relay.NetworkEVM, PluginType: types.Median, ContractID: "foo", OCRKeyBundleID: null.StringFrom("bar"), @@ -273,85 +275,60 @@ func TestOCR2OracleSpec(t *testing.T) { func TestWorkflowSpec_Validate(t *testing.T) { type fields struct { - ID int32 - WorkflowID string - Workflow string - WorkflowOwner string - WorkflowName string - CreatedAt time.Time - UpdatedAt time.Time + Workflow string } tests := []struct { - name string - fields fields - expectedErr error + name string + fields fields + wantWorkflowOwner string + wantWorkflowName string + + wantError bool }{ { name: "valid", fields: fields{ - WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef", - WorkflowOwner: "00000000000000000000000000000000000000aa", - WorkflowName: "ten bytes!", - }, - }, - { - name: "valid 0x prefix hex owner", - fields: fields{ - WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef", - WorkflowOwner: "0x00000000000000000000000000000000000000ff", - WorkflowName: "ten bytes!", + Workflow: pkgworkflows.WFYamlSpec(t, "workflow01", "0x0123456789012345678901234567890123456789"), }, + wantWorkflowOwner: "0123456789012345678901234567890123456789", // the workflow job spec strips the 0x prefix to limit to 40 characters + wantWorkflowName: "workflow01", }, { - name: "not hex owner", + name: "valid no name", fields: fields{ - WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef", - WorkflowOwner: "00000000000000000000000000000000000000az", - WorkflowName: "ten bytes!", + Workflow: pkgworkflows.WFYamlSpec(t, "", "0x0123456789012345678901234567890123456789"), }, - expectedErr: ErrInvalidWorkflowOwner, + wantWorkflowOwner: "0123456789012345678901234567890123456789", // the workflow job spec strips the 0x prefix to limit to 40 characters + wantWorkflowName: "", }, { - name: "not len 40 owner", + name: "valid no owner", fields: fields{ - WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef", - WorkflowOwner: "0000000000", - WorkflowName: "ten bytes!", + Workflow: pkgworkflows.WFYamlSpec(t, "workflow01", ""), }, - expectedErr: ErrInvalidWorkflowOwner, + wantWorkflowOwner: "", + wantWorkflowName: "workflow01", }, { - name: "not len 10 name", + name: "invalid ", fields: fields{ - WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef", - WorkflowOwner: "00000000000000000000000000000000000000aa", - WorkflowName: "not ten bytes!", + Workflow: "garbage", }, - expectedErr: ErrInvalidWorkflowName, - }, - { - name: "not len 64 id", - fields: fields{ - WorkflowID: "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f", - WorkflowOwner: "00000000000000000000000000000000000000aa", - WorkflowName: "ten bytes!", - }, - expectedErr: ErrInvalidWorkflowID, + wantError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := &WorkflowSpec{ - ID: tt.fields.ID, - WorkflowID: tt.fields.WorkflowID, - Workflow: tt.fields.Workflow, - WorkflowOwner: tt.fields.WorkflowOwner, - WorkflowName: tt.fields.WorkflowName, - CreatedAt: tt.fields.CreatedAt, - UpdatedAt: tt.fields.UpdatedAt, + Workflow: tt.fields.Workflow, } err := w.Validate() - assert.ErrorIs(t, err, tt.expectedErr) + require.Equal(t, tt.wantError, err != nil) + if !tt.wantError { + assert.NotEmpty(t, w.WorkflowID) + assert.Equal(t, tt.wantWorkflowOwner, w.WorkflowOwner) + assert.Equal(t, tt.wantWorkflowName, w.WorkflowName) + } }) } } diff --git a/core/services/job/orm.go b/core/services/job/orm.go index 4dc5478d11..efcb088284 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -31,6 +31,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" medianconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/median/config" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -414,7 +415,7 @@ func (o *orm) CreateJob(ctx context.Context, jb *Job) error { RETURNING id;` specID, err := tx.prepareQuerySpecID(ctx, sql, jb.WorkflowSpec) if err != nil { - return errors.Wrap(err, "failed to create WorkflowSpec for jobSpec") + return fmt.Errorf("failed to create WorkflowSpec for jobSpec given %v: %w", *jb.WorkflowSpec, err) } jb.WorkflowSpecID = &specID case StandardCapabilities: @@ -580,26 +581,29 @@ func ValidateKeyStoreMatch(ctx context.Context, spec *OCR2OracleSpec, keyStore k func validateKeyStoreMatchForRelay(ctx context.Context, network string, keyStore keystore.Master, key string) error { switch network { - case types.NetworkEVM: + case relay.NetworkEVM: _, err := keyStore.Eth().Get(ctx, key) if err != nil { return errors.Errorf("no EVM key matching: %q", key) } - case types.NetworkCosmos: + case relay.NetworkCosmos: _, err := keyStore.Cosmos().Get(key) if err != nil { return errors.Errorf("no Cosmos key matching: %q", key) } - case types.NetworkSolana: + case relay.NetworkSolana: _, err := keyStore.Solana().Get(key) if err != nil { return errors.Errorf("no Solana key matching: %q", key) } - case types.NetworkStarkNet: + case relay.NetworkStarkNet: _, err := keyStore.StarkNet().Get(key) if err != nil { return errors.Errorf("no Starknet key matching: %q", key) } + case relay.NetworkAptos: + // TODO BCI-2953 + return nil } return nil } diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 275d862570..eac6fa0d7a 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -26,26 +26,25 @@ import ( ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner" ocr2keepers21config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" - "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" - - "github.com/smartcontractkit/chainlink/v2/core/config/env" - - "github.com/smartcontractkit/chainlink-vrf/altbn_128" - dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg" - "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" + "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/core" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-vrf/altbn_128" + dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg" + "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -78,6 +77,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" functionsRelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" evmmercury "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" @@ -294,7 +294,7 @@ func (d *Delegate) OnDeleteJob(ctx context.Context, jb job.Job) error { return nil } // we only have clean to do for the EVM - if rid.Network == types.NetworkEVM { + if rid.Network == relay.NetworkEVM { return d.cleanupEVM(ctx, jb, rid) } return nil @@ -405,7 +405,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi return nil, ErrJobSpecNoRelayer{Err: err, PluginName: string(spec.PluginType)} } - if rid.Network == types.NetworkEVM { + if rid.Network == relay.NetworkEVM { lggr = logger.Sugared(lggr.With("evmChainID", rid.ChainID)) chain, err2 := d.legacyChains.Get(rid.ChainID) @@ -826,7 +826,7 @@ func (d *Delegate) newServicesMercury( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "mercury"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("mercury services: expected EVM relayer got %s", rid.Network) } relayer, err := d.RelayGetter.Get(rid) @@ -920,7 +920,7 @@ func (d *Delegate) newServicesLLO( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "streams"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("streams services: expected EVM relayer got %s", rid.Network) } relayer, err := d.RelayGetter.Get(rid) @@ -1103,7 +1103,7 @@ func (d *Delegate) newServicesDKG( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "DKG"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("DKG services: expected EVM relayer got %s", rid.Network) } @@ -1168,7 +1168,7 @@ func (d *Delegate) newServicesOCR2VRF( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "VRF"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("VRF services: expected EVM relayer got %s", rid.Network) } chain, err2 := d.legacyChains.Get(rid.ChainID) @@ -1280,10 +1280,10 @@ func (d *Delegate) newServicesOCR2VRF( lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) dkgReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { - return promwrapper.NewPromFactory(wrapped, "DKG", string(types.NetworkEVM), chain.ID()) + return promwrapper.NewPromFactory(wrapped, "DKG", string(relay.NetworkEVM), chain.ID()) } vrfReportingPluginFactoryDecorator := func(wrapped ocrtypes.ReportingPluginFactory) ocrtypes.ReportingPluginFactory { - return promwrapper.NewPromFactory(wrapped, "OCR2VRF", string(types.NetworkEVM), chain.ID()) + return promwrapper.NewPromFactory(wrapped, "OCR2VRF", string(relay.NetworkEVM), chain.ID()) } noopMonitoringEndpoint := telemetry.NoopAgent{} oracles, err2 := ocr2vrf.NewOCR2VRF(ocr2vrf.DKGVRFArgs{ @@ -1382,7 +1382,7 @@ func (d *Delegate) newServicesOCR2Keepers21( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keeper2"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("keeper2 services: expected EVM relayer got %s", rid.Network) } @@ -1535,7 +1535,7 @@ func (d *Delegate) newServicesOCR2Keepers20( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "keepers2.0"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("keepers2.0 services: expected EVM relayer got %s", rid.Network) } chain, err2 := d.legacyChains.Get(rid.ChainID) @@ -1663,7 +1663,7 @@ func (d *Delegate) newServicesOCR2Functions( if err != nil { return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "functions"} } - if rid.Network != types.NetworkEVM { + if rid.Network != relay.NetworkEVM { return nil, fmt.Errorf("functions services: expected EVM relayer got %s", rid.Network) } chain, err := d.legacyChains.Get(rid.ChainID) diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go index dbc400a346..06f1bf3583 100644 --- a/core/services/ocr2/plugins/dkg/persistence/db_test.go +++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go @@ -10,19 +10,19 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/types" ocr2vrftypes "github.com/smartcontractkit/chainlink-vrf/types" "github.com/smartcontractkit/chainlink-vrf/types/hash" "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" ) func setup(t testing.TB) (ocr2vrftypes.DKGSharePersistence, *sqlx.DB) { db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) - return NewShareDB(db, lggr, big.NewInt(1337), types.NetworkEVM), db + return NewShareDB(db, lggr, big.NewInt(1337), relay.NetworkEVM), db } func TestShareDB_WriteShareRecords(t *testing.T) { diff --git a/core/services/ocr2/plugins/mercury/integration_plugin_test.go b/core/services/ocr2/plugins/mercury/integration_plugin_test.go index 74285f32dc..4089cc485c 100644 --- a/core/services/ocr2/plugins/mercury/integration_plugin_test.go +++ b/core/services/ocr2/plugins/mercury/integration_plugin_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/smartcontractkit/chainlink/v2/core/config/env" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func TestIntegration_MercuryV1_Plugin(t *testing.T) { @@ -15,8 +16,8 @@ func TestIntegration_MercuryV1_Plugin(t *testing.T) { } func TestIntegration_MercuryV2_Plugin(t *testing.T) { + testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/MERC-5697") t.Setenv(string(env.MercuryPlugin.Cmd), "chainlink-mercury") - integration_MercuryV2(t) } diff --git a/core/services/ocr2/plugins/mercury/integration_test.go b/core/services/ocr2/plugins/mercury/integration_test.go index 680b05bd4d..832a39237e 100644 --- a/core/services/ocr2/plugins/mercury/integration_test.go +++ b/core/services/ocr2/plugins/mercury/integration_test.go @@ -184,15 +184,17 @@ func integration_MercuryV1(t *testing.T) { bootstrapNode := Node{App: appBootstrap, KeyBundle: bootstrapKb} logObservers = append(logObservers, observedLogs) - // Commit blocks to finality depth to ensure LogPoller has finalized blocks to read from - ch, err := bootstrapNode.App.GetRelayers().LegacyEVMChains().Get(testutils.SimulatedChainID.String()) - require.NoError(t, err) - finalityDepth := ch.Config().EVM().FinalityDepth() - for i := 0; i < int(finalityDepth); i++ { - backend.Commit() - } - - fromBlock := int(finalityDepth) // cannot use zero, start from finality depth + // cannot use zero, start from finality depth + fromBlock := func() int { + // Commit blocks to finality depth to ensure LogPoller has finalized blocks to read from + ch, err := bootstrapNode.App.GetRelayers().LegacyEVMChains().Get(testutils.SimulatedChainID.String()) + require.NoError(t, err) + finalityDepth := ch.Config().EVM().FinalityDepth() + for i := 0; i < int(finalityDepth); i++ { + backend.Commit() + } + return int(finalityDepth) + }() // Set up n oracles var ( @@ -225,9 +227,8 @@ func integration_MercuryV1(t *testing.T) { createBridge := func(name string, i int, p *big.Int, borm bridges.ORM) (bridgeName string) { bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - var b []byte - b, err = io.ReadAll(req.Body) - require.NoError(t, err) + b, herr := io.ReadAll(req.Body) + require.NoError(t, herr) require.Equal(t, `{"data":{"from":"ETH","to":"USD"}}`, string(b)) r := rand.Int63n(101) @@ -235,13 +236,13 @@ func integration_MercuryV1(t *testing.T) { res.WriteHeader(http.StatusOK) val := decimal.NewFromBigInt(p, 0).Div(decimal.NewFromInt(multiplier)).Add(decimal.NewFromInt(int64(i)).Div(decimal.NewFromInt(100))).String() resp := fmt.Sprintf(`{"result": %s}`, val) - _, err = res.Write([]byte(resp)) - require.NoError(t, err) + _, herr = res.Write([]byte(resp)) + require.NoError(t, herr) } else { res.WriteHeader(http.StatusInternalServerError) resp := `{"error": "pError test error"}` - _, err = res.Write([]byte(resp)) - require.NoError(t, err) + _, herr = res.Write([]byte(resp)) + require.NoError(t, herr) } })) t.Cleanup(bridge.Close) @@ -328,7 +329,7 @@ func integration_MercuryV1(t *testing.T) { "offchainConfig", offchainConfig, ) - _, err = verifier.SetConfig( + _, ferr := verifier.SetConfig( steve, feed.id, signerAddresses, @@ -339,7 +340,7 @@ func integration_MercuryV1(t *testing.T) { offchainConfig, nil, ) - require.NoError(t, err) + require.NoError(t, ferr) backend.Commit() } @@ -580,9 +581,8 @@ func integration_MercuryV2(t *testing.T) { createBridge := func(name string, i int, p *big.Int, borm bridges.ORM) (bridgeName string) { bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - var b []byte - b, err = io.ReadAll(req.Body) - require.NoError(t, err) + b, herr := io.ReadAll(req.Body) + require.NoError(t, herr) require.Equal(t, `{"data":{"from":"ETH","to":"USD"}}`, string(b)) r := rand.Int63n(101) @@ -590,13 +590,13 @@ func integration_MercuryV2(t *testing.T) { res.WriteHeader(http.StatusOK) val := decimal.NewFromBigInt(p, 0).Div(decimal.NewFromInt(multiplier)).Add(decimal.NewFromInt(int64(i)).Div(decimal.NewFromInt(100))).String() resp := fmt.Sprintf(`{"result": %s}`, val) - _, err = res.Write([]byte(resp)) - require.NoError(t, err) + _, herr = res.Write([]byte(resp)) + require.NoError(t, herr) } else { res.WriteHeader(http.StatusInternalServerError) resp := `{"error": "pError test error"}` - _, err = res.Write([]byte(resp)) - require.NoError(t, err) + _, herr = res.Write([]byte(resp)) + require.NoError(t, herr) } })) t.Cleanup(bridge.Close) @@ -668,7 +668,7 @@ func integration_MercuryV2(t *testing.T) { } for _, feed := range feeds { - _, err = verifier.SetConfig( + _, ferr := verifier.SetConfig( steve, feed.id, signerAddresses, @@ -679,7 +679,7 @@ func integration_MercuryV2(t *testing.T) { offchainConfig, nil, ) - require.NoError(t, err) + require.NoError(t, ferr) backend.Commit() } @@ -870,9 +870,8 @@ func integration_MercuryV3(t *testing.T) { createBridge := func(name string, i int, p *big.Int, borm bridges.ORM) (bridgeName string) { bridge := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - var b []byte - b, err = io.ReadAll(req.Body) - require.NoError(t, err) + b, herr := io.ReadAll(req.Body) + require.NoError(t, herr) require.Equal(t, `{"data":{"from":"ETH","to":"USD"}}`, string(b)) r := rand.Int63n(101) @@ -880,13 +879,13 @@ func integration_MercuryV3(t *testing.T) { res.WriteHeader(http.StatusOK) val := decimal.NewFromBigInt(p, 0).Div(decimal.NewFromInt(multiplier)).Add(decimal.NewFromInt(int64(i)).Div(decimal.NewFromInt(100))).String() resp := fmt.Sprintf(`{"result": %s}`, val) - _, err = res.Write([]byte(resp)) - require.NoError(t, err) + _, herr = res.Write([]byte(resp)) + require.NoError(t, herr) } else { res.WriteHeader(http.StatusInternalServerError) resp := `{"error": "pError test error"}` - _, err = res.Write([]byte(resp)) - require.NoError(t, err) + _, herr = res.Write([]byte(resp)) + require.NoError(t, herr) } })) t.Cleanup(bridge.Close) @@ -961,7 +960,7 @@ func integration_MercuryV3(t *testing.T) { } for _, feed := range feeds { - _, err = verifier.SetConfig( + _, ferr := verifier.SetConfig( steve, feed.id, signerAddresses, @@ -972,7 +971,7 @@ func integration_MercuryV3(t *testing.T) { offchainConfig, nil, ) - require.NoError(t, err) + require.NoError(t, ferr) backend.Commit() } diff --git a/core/services/ocr2/plugins/mercury/plugin_test.go b/core/services/ocr2/plugins/mercury/plugin_test.go index d617d63116..95aaabec14 100644 --- a/core/services/ocr2/plugins/mercury/plugin_test.go +++ b/core/services/ocr2/plugins/mercury/plugin_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink-common/pkg/loop" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -73,7 +74,7 @@ var ( ID: 7, ContractID: "phony", FeedID: ptr(common.BytesToHash([]byte{1, 2, 3})), - Relay: commontypes.NetworkEVM, + Relay: relay.NetworkEVM, ChainID: "1", }, PipelineSpec: &pipeline.Spec{}, diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go index 56c200f9b1..ce7325a96b 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v20/registry.go @@ -215,7 +215,7 @@ func (r *EvmRegistry) Start(_ context.Context) error { defer cancel() err := f(ctx) if err != nil { - lggr.Errorf("failed to initialize upkeeps", err) + lggr.Errorf("failed to initialize upkeeps; error %v", err) } for { @@ -223,7 +223,7 @@ func (r *EvmRegistry) Start(_ context.Context) error { case <-tmr.C: err = f(ctx) if err != nil { - lggr.Errorf("failed to re-initialize upkeeps", err) + lggr.Errorf("failed to re-initialize upkeeps; error %v", err) } tmr.Reset(reInitializationDelay) case <-ctx.Done(): @@ -245,7 +245,7 @@ func (r *EvmRegistry) Start(_ context.Context) error { case <-ticker.C: err := f(ctx) if err != nil { - lggr.Errorf("failed to poll logs for upkeeps", err) + lggr.Errorf("failed to poll logs for upkeeps; error %v", err) } case <-ctx.Done(): ticker.Stop() @@ -265,7 +265,7 @@ func (r *EvmRegistry) Start(_ context.Context) error { case l := <-ch: err := f(ctx, l) if err != nil { - lggr.Errorf("failed to process log for upkeep", err) + lggr.Errorf("failed to process log for upkeep; error %v", err) } case <-ctx.Done(): return @@ -420,16 +420,16 @@ func (r *EvmRegistry) processUpkeepStateLog(ctx context.Context, l logpoller.Log switch l := abilog.(type) { case *keeper_registry_wrapper2_0.KeeperRegistryUpkeepRegistered: - r.lggr.Debugf("KeeperRegistryUpkeepRegistered log detected for upkeep ID %s in transaction %s", l.Id.String(), hash) + r.lggr.Debugf("KeeperRegistryUpkeepRegistered log detected for upkeep ID %s in transaction %s", l.Id, hash) r.addToActive(ctx, l.Id, false) case *keeper_registry_wrapper2_0.KeeperRegistryUpkeepReceived: - r.lggr.Debugf("KeeperRegistryUpkeepReceived log detected for upkeep ID %s in transaction %s", l.Id.String(), hash) + r.lggr.Debugf("KeeperRegistryUpkeepReceived log detected for upkeep ID %s in transaction %s", l.Id, hash) r.addToActive(ctx, l.Id, false) case *keeper_registry_wrapper2_0.KeeperRegistryUpkeepUnpaused: - r.lggr.Debugf("KeeperRegistryUpkeepUnpaused log detected for upkeep ID %s in transaction %s", l.Id.String(), hash) + r.lggr.Debugf("KeeperRegistryUpkeepUnpaused log detected for upkeep ID %s in transaction %s", l.Id, hash) r.addToActive(ctx, l.Id, false) case *keeper_registry_wrapper2_0.KeeperRegistryUpkeepGasLimitSet: - r.lggr.Debugf("KeeperRegistryUpkeepGasLimitSet log detected for upkeep ID %s in transaction %s", l.Id.String(), hash) + r.lggr.Debugf("KeeperRegistryUpkeepGasLimitSet log detected for upkeep ID %s in transaction %s", l.Id, hash) r.addToActive(ctx, l.Id, true) } @@ -447,7 +447,7 @@ func (r *EvmRegistry) addToActive(ctx context.Context, id *big.Int, force bool) if _, ok := r.active[id.String()]; !ok || force { actives, err := r.getUpkeepConfigs(ctx, []*big.Int{id}) if err != nil { - r.lggr.Errorf("failed to get upkeep configs during adding active upkeep: %w", err) + r.lggr.Errorf("failed to get upkeep configs during adding active upkeep: %v", err) return } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go index 3a7d329ac0..d07af8a8de 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/block_subscriber.go @@ -147,11 +147,11 @@ func (bs *BlockSubscriber) initialize(ctx context.Context) { // initialize the blocks map with the recent blockSize blocks blocks, err := bs.getBlockRange(ctx) if err != nil { - bs.lggr.Errorf("failed to get block range", err) + bs.lggr.Errorf("failed to get block range; error %v", err) } err = bs.initializeBlocks(ctx, blocks) if err != nil { - bs.lggr.Errorf("failed to get log poller blocks", err) + bs.lggr.Errorf("failed to get log poller blocks; error %v", err) } _, bs.unsubscribe = bs.hb.Subscribe(&headWrapper{headC: bs.headC, lggr: bs.lggr}) } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go index 46314dde41..ace17ca2db 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go @@ -145,8 +145,7 @@ func TestIntegration_LogEventProvider(t *testing.T) { } func TestIntegration_LogEventProvider_UpdateConfig(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) backend, stopMining, accounts := setupBackend(t) defer stopMining() diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go index 5ef321cbf7..f00459dee6 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/recoverer.go @@ -724,7 +724,7 @@ func (r *logRecoverer) updateBlockTime(ctx context.Context) { currentBlockTime := r.blockTime.Load() newBlockTime := int64(blockTime) if currentBlockTime > 0 && (int64(math.Abs(float64(currentBlockTime-newBlockTime)))*100/currentBlockTime) > 20 { - r.lggr.Warnf("updating blocktime from %d to %d, this change is larger than 20%", currentBlockTime, newBlockTime) + r.lggr.Warnf("updating blocktime from %d to %d, this change is larger than 20%%", currentBlockTime, newBlockTime) } else { r.lggr.Debugf("updating blocktime from %d to %d", currentBlockTime, newBlockTime) } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go index 6bab073b9b..cb7e689b04 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go @@ -215,7 +215,7 @@ func (r *EvmRegistry) Start(ctx context.Context) error { lggr := r.lggr.With("where", "upkeeps_referesh") err := r.refreshActiveUpkeeps(ctx) if err != nil { - lggr.Errorf("failed to initialize upkeeps", err) + lggr.Errorf("failed to initialize upkeeps; error %v", err) } ticker := time.NewTicker(refreshInterval) @@ -226,7 +226,7 @@ func (r *EvmRegistry) Start(ctx context.Context) error { case <-ticker.C: err = r.refreshActiveUpkeeps(ctx) if err != nil { - lggr.Errorf("failed to refresh upkeeps", err) + lggr.Errorf("failed to refresh upkeeps; error %v", err) } case <-ctx.Done(): return @@ -244,7 +244,7 @@ func (r *EvmRegistry) Start(ctx context.Context) error { case <-ticker.C: err := r.pollUpkeepStateLogs(ctx) if err != nil { - lggr.Errorf("failed to poll logs for upkeeps", err) + lggr.Errorf("failed to poll logs for upkeeps; error %v", err) } case <-ctx.Done(): return @@ -261,7 +261,7 @@ func (r *EvmRegistry) Start(ctx context.Context) error { case l := <-ch: err := r.processUpkeepStateLog(ctx, l) if err != nil { - lggr.Errorf("failed to process log for upkeep", err) + lggr.Errorf("failed to process log for upkeep; error %v", err) } case <-ctx.Done(): return @@ -464,39 +464,39 @@ func (r *EvmRegistry) processUpkeepStateLog(ctx context.Context, l logpoller.Log switch l := abilog.(type) { case *ac.IAutomationV21PlusCommonUpkeepPaused: - r.lggr.Debugf("KeeperRegistryUpkeepPaused log detected for upkeep ID %s in transaction %s", l.Id.String(), txHash) + r.lggr.Debugf("KeeperRegistryUpkeepPaused log detected for upkeep ID %s in transaction %s", l.Id, txHash) r.removeFromActive(ctx, l.Id) case *ac.IAutomationV21PlusCommonUpkeepCanceled: - r.lggr.Debugf("KeeperRegistryUpkeepCanceled log detected for upkeep ID %s in transaction %s", l.Id.String(), txHash) + r.lggr.Debugf("KeeperRegistryUpkeepCanceled log detected for upkeep ID %s in transaction %s", l.Id, txHash) r.removeFromActive(ctx, l.Id) case *ac.IAutomationV21PlusCommonUpkeepMigrated: - r.lggr.Debugf("AutomationV2CommonUpkeepMigrated log detected for upkeep ID %s in transaction %s", l.Id.String(), txHash) + r.lggr.Debugf("AutomationV2CommonUpkeepMigrated log detected for upkeep ID %s in transaction %s", l.Id, txHash) r.removeFromActive(ctx, l.Id) case *ac.IAutomationV21PlusCommonUpkeepTriggerConfigSet: - r.lggr.Debugf("KeeperRegistryUpkeepTriggerConfigSet log detected for upkeep ID %s in transaction %s", l.Id.String(), txHash) + r.lggr.Debugf("KeeperRegistryUpkeepTriggerConfigSet log detected for upkeep ID %s in transaction %s", l.Id, txHash) if err := r.updateTriggerConfig(ctx, l.Id, l.TriggerConfig, rawLog.BlockNumber); err != nil { - r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepTriggerConfigSet for upkeep ID %s: %s", l.Id.String(), err) + r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepTriggerConfigSet for upkeep ID %s: %s", l.Id, err) } case *ac.IAutomationV21PlusCommonUpkeepRegistered: uid := &ocr2keepers.UpkeepIdentifier{} uid.FromBigInt(l.Id) trigger := core.GetUpkeepType(*uid) - r.lggr.Debugf("KeeperRegistryUpkeepRegistered log detected for upkeep ID %s (trigger=%d) in transaction %s", l.Id.String(), trigger, txHash) + r.lggr.Debugf("KeeperRegistryUpkeepRegistered log detected for upkeep ID %s (trigger=%d) in transaction %s", l.Id, trigger, txHash) r.active.Add(l.Id) if err := r.updateTriggerConfig(ctx, l.Id, nil, rawLog.BlockNumber); err != nil { - r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepRegistered for upkeep ID %s: %s", err) + r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepRegistered for upkeep ID %s: %s", l.Id, err) } case *ac.IAutomationV21PlusCommonUpkeepReceived: - r.lggr.Debugf("KeeperRegistryUpkeepReceived log detected for upkeep ID %s in transaction %s", l.Id.String(), txHash) + r.lggr.Debugf("KeeperRegistryUpkeepReceived log detected for upkeep ID %s in transaction %s", l.Id, txHash) r.active.Add(l.Id) if err := r.updateTriggerConfig(ctx, l.Id, nil, rawLog.BlockNumber); err != nil { - r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepReceived for upkeep ID %s: %s", err) + r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepReceived for upkeep ID %s: %s", l.Id, err) } case *ac.IAutomationV21PlusCommonUpkeepUnpaused: - r.lggr.Debugf("KeeperRegistryUpkeepUnpaused log detected for upkeep ID %s in transaction %s", l.Id.String(), txHash) + r.lggr.Debugf("KeeperRegistryUpkeepUnpaused log detected for upkeep ID %s in transaction %s", l.Id, txHash) r.active.Add(l.Id) if err := r.updateTriggerConfig(ctx, l.Id, nil, rawLog.BlockNumber); err != nil { - r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepUnpaused for upkeep ID %s: %s", err) + r.lggr.Warnf("failed to update trigger config upon AutomationV2CommonUpkeepUnpaused for upkeep ID %s: %s", l.Id, err) } default: r.lggr.Debugf("Unknown log detected for log %+v in transaction %s", l, txHash) diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go index ef0089921c..f14c9865c3 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_check_pipeline.go @@ -148,7 +148,7 @@ func (r *EvmRegistry) verifyLogExists(ctx context.Context, upkeepId *big.Int, p // if this block number/hash combo exists in block subscriber, this block and tx still exists on chain and is valid // the block hash in block subscriber might be slightly outdated, if it doesn't match then we fetch the latest from RPC. if ok && h == logBlockHash.Hex() { - r.lggr.Debugf("tx hash %s exists on chain at block number %d, block hash %s for upkeepId %s", hexutil.Encode(p.Trigger.LogTriggerExtension.TxHash[:]), logBlockHash.Hex(), logBlockNumber, upkeepId) + r.lggr.Debugf("tx hash %s exists on chain at block number %d, block hash %s for upkeepId %s", hexutil.Encode(p.Trigger.LogTriggerExtension.TxHash[:]), logBlockNumber, logBlockHash.Hex(), upkeepId) return encoding.UpkeepFailureReasonNone, encoding.NoPipelineError, false } // if this block does not exist in the block subscriber, the block which this log lived on was probably re-orged diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index 1c9c602539..2ce9ff3d24 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -201,6 +201,11 @@ func getUpkeepIdFromTx(t *testing.T, registry *keeper_registry_wrapper2_0.Keeper } func TestIntegration_KeeperPluginBasic(t *testing.T) { + testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/AUTO-11072") + runKeeperPluginBasic(t) +} + +func runKeeperPluginBasic(t *testing.T) { g := gomega.NewWithT(t) lggr := logger.TestLogger(t) diff --git a/core/services/ocr2/plugins/threshold/decryption_queue_test.go b/core/services/ocr2/plugins/threshold/decryption_queue_test.go index 2a9f8d4c85..a017b883b3 100644 --- a/core/services/ocr2/plugins/threshold/decryption_queue_test.go +++ b/core/services/ocr2/plugins/threshold/decryption_queue_test.go @@ -36,8 +36,7 @@ func Test_decryptionQueue_Decrypt_ReturnResultAfterCallingDecrypt(t *testing.T) dq.SetResult([]byte("1"), []byte("decrypted"), nil) }() - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) pt, err := dq.Decrypt(ctx, []byte("1"), []byte("encrypted")) require.NoError(t, err) @@ -50,8 +49,7 @@ func Test_decryptionQueue_Decrypt_CiphertextIdTooLarge(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(1, 1000, 16, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) _, err := dq.Decrypt(ctx, []byte("largeCiphertextId"), []byte("ciphertext")) assert.Equal(t, err.Error(), "ciphertextId too large") @@ -61,8 +59,7 @@ func Test_decryptionQueue_Decrypt_EmptyCiphertextId(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(1, 1000, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) _, err := dq.Decrypt(ctx, []byte(""), []byte("ciphertext")) assert.Equal(t, err.Error(), "ciphertextId is empty") @@ -72,8 +69,7 @@ func Test_decryptionQueue_Decrypt_CiphertextTooLarge(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(1, 10, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) _, err := dq.Decrypt(ctx, []byte("1"), []byte("largeciphertext")) assert.Equal(t, err.Error(), "ciphertext too large") @@ -83,8 +79,7 @@ func Test_decryptionQueue_Decrypt_EmptyCiphertext(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(1, 1000, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) _, err := dq.Decrypt(ctx, []byte("1"), []byte("")) assert.Equal(t, err.Error(), "ciphertext is empty") @@ -94,8 +89,7 @@ func Test_decryptionQueue_Decrypt_DuplicateCiphertextId(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(1, 1000, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) go func() { _, err := dq.Decrypt(ctx, []byte("1"), []byte("encrypted")) @@ -179,8 +173,7 @@ func Test_decryptionQueue_GetCiphertext(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(3, 1000, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) go func() { _, err := dq.Decrypt(ctx, []byte("7"), []byte("encrypted")) @@ -210,8 +203,7 @@ func Test_decryptionQueue_Decrypt_DecryptCalledAfterReadyResult(t *testing.T) { dq.SetResult([]byte("9"), []byte("decrypted"), nil) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) pt, err := dq.Decrypt(ctx, []byte("9"), []byte("encrypted")) require.NoError(t, err) @@ -264,8 +256,7 @@ func Test_decryptionQueue_Decrypt_UserErrorDuringDecryption(t *testing.T) { dq.SetResult(ciphertextId, nil, decryptionPlugin.ErrAggregation) }() - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) _, err := dq.Decrypt(ctx, ciphertextId, []byte("encrypted")) assert.Equal(t, err.Error(), "pending decryption request for ciphertextId 0x120f was closed without a response") @@ -281,8 +272,7 @@ func Test_decryptionQueue_Decrypt_HandleClosedChannelWithoutPlaintextResponse(t close(dq.pendingRequests[string(ciphertextId)].chPlaintext) }() - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) _, err := dq.Decrypt(ctx, ciphertextId, []byte("encrypted")) assert.Equal(t, err.Error(), "pending decryption request for ciphertextId 0x00ff was closed without a response") @@ -380,8 +370,7 @@ func Test_decryptionQueue_GetRequests_PendingRequestQueueShorterThanRequestCount lggr := logger.TestLogger(t) dq := NewDecryptionQueue(4, 1000, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) go func() { _, err := dq.Decrypt(ctx, []byte("11"), []byte("encrypted")) @@ -425,8 +414,7 @@ func Test_decryptionQueue_Start(t *testing.T) { lggr := logger.TestLogger(t) dq := NewDecryptionQueue(4, 1000, 64, testutils.WaitTimeout(t), lggr) - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() + ctx := testutils.Context(t) err := dq.Start(ctx) diff --git a/core/services/ocr2/validate/config.go b/core/services/ocr2/validate/config.go index d22bd781d1..62815e1976 100644 --- a/core/services/ocr2/validate/config.go +++ b/core/services/ocr2/validate/config.go @@ -7,9 +7,9 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) // OCR2Config contains OCR2 configurations for a job. @@ -51,7 +51,7 @@ func ToLocalConfig(ocr2Config OCR2Config, insConf InsecureConfig, spec job.OCR2O ContractTransmitterTransmitTimeout: ocr2Config.ContractTransmitterTransmitTimeout(), DatabaseTimeout: ocr2Config.DatabaseTimeout(), } - if spec.Relay == commontypes.NetworkSolana && env.MedianPlugin.Cmd.Get() != "" { + if spec.Relay == relay.NetworkSolana && env.MedianPlugin.Cmd.Get() != "" { // Work around for Solana Feeds configured with zero values to support LOOP Plugins. minOCR2MaxDurationQuery, err := getMinOCR2MaxDurationQuery() if err != nil { diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go index 2d2f1493d0..8fa9b1f82a 100644 --- a/core/services/ocr2/validate/validate.go +++ b/core/services/ocr2/validate/validate.go @@ -12,6 +12,7 @@ import ( "github.com/lib/pq" "github.com/pelletier/go-toml" pkgerrors "github.com/pkg/errors" + libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -28,6 +29,7 @@ import ( ocr2vrfconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2vrf/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/plugins" ) @@ -58,7 +60,7 @@ func ValidatedOracleSpecToml(ctx context.Context, config OCR2Config, insConf Ins if jb.Type != job.OffchainReporting2 { return jb, pkgerrors.Errorf("the only supported type is currently 'offchainreporting2', got %s", jb.Type) } - if _, ok := types.SupportedRelays[spec.Relay]; !ok { + if _, ok := relay.SupportedNetworks[spec.Relay]; !ok { return jb, pkgerrors.Errorf("no such relay %v supported", spec.Relay) } if len(spec.P2PV2Bootstrappers) > 0 { diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go index b641bd2b3c..ec50db18aa 100644 --- a/core/services/ocrcommon/telemetry.go +++ b/core/services/ocrcommon/telemetry.go @@ -458,7 +458,7 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta // We rely on task results to be sorted in the correct order benchmarkPriceTask := allTasks.GetNextTaskOf(startTask) if benchmarkPriceTask == nil { - e.lggr.Warnf("cannot parse enhanced EA telemetry benchmark price, task is nil, job %d, id %s", e.job.ID) + e.lggr.Warnf("cannot parse enhanced EA telemetry benchmark price, task is nil, job %d", e.job.ID) return 0, 0, 0 } if benchmarkPriceTask.Task.Type() == pipeline.TaskTypeJSONParse { @@ -479,7 +479,7 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta bidTask := allTasks.GetNextTaskOf(*benchmarkPriceTask) if bidTask == nil { - e.lggr.Warnf("cannot parse enhanced EA telemetry bid price, task is nil, job %d, id %s", e.job.ID) + e.lggr.Warnf("cannot parse enhanced EA telemetry bid price, task is nil, job %d, id %s", e.job.ID, benchmarkPriceTask.Task.DotID()) return benchmarkPrice, 0, 0 } @@ -496,7 +496,7 @@ func (e *EnhancedTelemetryService[T]) getPricesFromResults(startTask pipeline.Ta askTask := allTasks.GetNextTaskOf(*bidTask) if askTask == nil { - e.lggr.Warnf("cannot parse enhanced EA telemetry ask price, task is nil, job %d, id %s", e.job.ID) + e.lggr.Warnf("cannot parse enhanced EA telemetry ask price, task is nil, job %d, id %s", e.job.ID, benchmarkPriceTask.Task.DotID()) return benchmarkPrice, bidPrice, 0 } if askTask != nil && askTask.Task.Type() == pipeline.TaskTypeJSONParse { diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index e816e96dad..57c9bfd15b 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -3,6 +3,7 @@ package pipeline import ( "context" "fmt" + "io" "net/http" "sort" "sync" @@ -108,10 +109,22 @@ var ( ) ) -func NewRunner(orm ORM, btORM bridges.ORM, cfg Config, bridgeCfg BridgeConfig, legacyChains legacyevm.LegacyChainContainer, ethks ETHKeyStore, vrfks VRFKeyStore, lggr logger.Logger, httpClient, unrestrictedHTTPClient *http.Client) *runner { +func NewRunner( + orm ORM, + btORM bridges.ORM, + cfg Config, + bridgeCfg BridgeConfig, + legacyChains legacyevm.LegacyChainContainer, + ethks ETHKeyStore, + vrfks VRFKeyStore, + lggr logger.Logger, + httpClient, unrestrictedHTTPClient *http.Client, +) *runner { + lggr = lggr.Named("PipelineRunner") + r := &runner{ orm: orm, - btORM: btORM, + btORM: bridges.NewCache(btORM, lggr, bridges.DefaultUpsertInterval), config: cfg, bridgeConfig: bridgeCfg, legacyEVMChains: legacyChains, @@ -120,18 +133,20 @@ func NewRunner(orm ORM, btORM bridges.ORM, cfg Config, bridgeCfg BridgeConfig, l chStop: make(chan struct{}), wgDone: sync.WaitGroup{}, runFinished: func(*Run) {}, - lggr: lggr.Named("PipelineRunner"), + lggr: lggr, httpClient: httpClient, unrestrictedHTTPClient: unrestrictedHTTPClient, } + r.runReaperWorker = commonutils.NewSleeperTask( commonutils.SleeperFuncTask(r.runReaper, "PipelineRunnerReaper"), ) + return r } // Start starts Runner. -func (r *runner) Start(context.Context) error { +func (r *runner) Start(ctx context.Context) error { return r.StartOnce("PipelineRunner", func() error { r.wgDone.Add(1) go r.scheduleUnfinishedRuns() @@ -139,6 +154,13 @@ func (r *runner) Start(context.Context) error { r.wgDone.Add(1) go r.runReaperLoop() } + + // the btORM can be a cache service or a static ORM if the constructor changes + service, isService := r.btORM.(services.Service) + if isService { + return service.Start(ctx) + } + return nil }) } @@ -147,6 +169,12 @@ func (r *runner) Close() error { return r.StopOnce("PipelineRunner", func() error { close(r.chStop) r.wgDone.Wait() + + // the btORM can be a cache service or a static ORM if the constructor changes + if closer, isCloser := r.btORM.(io.Closer); isCloser { + return closer.Close() + } + return nil }) } @@ -156,7 +184,16 @@ func (r *runner) Name() string { } func (r *runner) HealthReport() map[string]error { - return map[string]error{r.Name(): r.Healthy()} + runnerHealth := map[string]error{r.Name(): r.Healthy()} + + service, isService := r.btORM.(services.HealthReporter) + if !isService { + return runnerHealth + } + + services.CopyHealth(runnerHealth, service.HealthReport()) + + return runnerHealth } func (r *runner) destroy() { @@ -311,6 +348,7 @@ func (r *runner) InitializePipeline(spec Spec) (pipeline *Pipeline, err error) { case TaskTypeBridge: task.(*BridgeTask).config = r.config task.(*BridgeTask).bridgeConfig = r.bridgeConfig + // orm added to BridgeTask task.(*BridgeTask).orm = r.btORM task.(*BridgeTask).specId = spec.ID // URL is "safe" because it comes from the node's own database. We diff --git a/core/services/pipeline/task.bridge_test.go b/core/services/pipeline/task.bridge_test.go index 417f781af7..2efff2af6b 100644 --- a/core/services/pipeline/task.bridge_test.go +++ b/core/services/pipeline/task.bridge_test.go @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/require" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -1069,7 +1070,11 @@ func TestBridgeTask_AdapterResponseStatusFailure(t *testing.T) { feedURL, err := url.ParseRequestURI(s1.URL) require.NoError(t, err) - orm := bridges.NewORM(db) + // orm := bridges.NewORM(db) + orm := bridges.NewCache(bridges.NewORM(db), logger.TestLogger(t), bridges.DefaultUpsertInterval) + + servicetest.Run(t, orm) + _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{URL: feedURL.String()}) task := pipeline.BridgeTask{ diff --git a/core/services/relay/evm/binding.go b/core/services/relay/evm/binding.go index d7a04dcc9b..9c7fd186de 100644 --- a/core/services/relay/evm/binding.go +++ b/core/services/relay/evm/binding.go @@ -8,10 +8,10 @@ import ( ) type readBinding interface { - GetLatestValue(ctx context.Context, params, returnVal any) error - QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) Bind(ctx context.Context, binding commontypes.BoundContract) error SetCodec(codec commontypes.RemoteCodec) Register(ctx context.Context) error Unregister(ctx context.Context) error + GetLatestValue(ctx context.Context, params, returnVal any) error + QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) } diff --git a/core/services/relay/evm/bindings.go b/core/services/relay/evm/bindings.go index e13fcbc02d..9ad73c0192 100644 --- a/core/services/relay/evm/bindings.go +++ b/core/services/relay/evm/bindings.go @@ -5,44 +5,54 @@ import ( "fmt" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ) -// key is contract name -type contractBindings map[string]readBindings +// bindings manage all contract bindings, key is contract name. +type bindings map[string]*contractBinding -// key is read name -type readBindings map[string]readBinding - -func (b contractBindings) GetReadBinding(contractName, readName string) (readBinding, error) { - rb, rbExists := b[contractName] - if !rbExists { +func (b bindings) GetReadBinding(contractName, readName string) (readBinding, error) { + // GetReadBindings should only be called after Chain Reader init. + cb, cbExists := b[contractName] + if !cbExists { return nil, fmt.Errorf("%w: no contract named %s", commontypes.ErrInvalidType, contractName) } - reader, readerExists := rb[readName] - if !readerExists { + rb, rbExists := cb.readBindings[readName] + if !rbExists { return nil, fmt.Errorf("%w: no readName named %s in contract %s", commontypes.ErrInvalidType, readName, contractName) } - return reader, nil + return rb, nil } -func (b contractBindings) AddReadBinding(contractName, readName string, reader readBinding) { - rbs, rbsExists := b[contractName] - if !rbsExists { - rbs = readBindings{} - b[contractName] = rbs +// AddReadBinding adds read bindings. Calling this outside of Chain Reader init is not thread safe. +func (b bindings) AddReadBinding(contractName, readName string, rb readBinding) { + cb, cbExists := b[contractName] + if !cbExists { + cb = &contractBinding{ + name: contractName, + readBindings: make(map[string]readBinding), + } + b[contractName] = cb } - rbs[readName] = reader + cb.readBindings[readName] = rb } -func (b contractBindings) Bind(ctx context.Context, boundContracts []commontypes.BoundContract) error { +// Bind binds contract addresses to contract bindings and read bindings. +// Bind also registers the common contract polling filter and eventBindings polling filters. +func (b bindings) Bind(ctx context.Context, lp logpoller.LogPoller, boundContracts []commontypes.BoundContract) error { for _, bc := range boundContracts { - rbs, rbsExist := b[bc.Name] - if !rbsExist { + cb, cbExists := b[bc.Name] + if !cbExists { return fmt.Errorf("%w: no contract named %s", commontypes.ErrInvalidConfig, bc.Name) } - for _, r := range rbs { - if err := r.Bind(ctx, bc); err != nil { + + if err := cb.Bind(ctx, lp, bc); err != nil { + return err + } + + for _, rb := range cb.readBindings { + if err := rb.Bind(ctx, bc); err != nil { return err } } @@ -50,12 +60,10 @@ func (b contractBindings) Bind(ctx context.Context, boundContracts []commontypes return nil } -func (b contractBindings) ForEach(ctx context.Context, fn func(readBinding, context.Context) error) error { - for _, rbs := range b { - for _, rb := range rbs { - if err := fn(rb, ctx); err != nil { - return err - } +func (b bindings) ForEach(ctx context.Context, fn func(context.Context, *contractBinding) error) error { + for _, cb := range b { + if err := fn(ctx, cb); err != nil { + return err } } return nil diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index bd769e05f3..9cfe846d55 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -5,11 +5,12 @@ import ( "errors" "fmt" "reflect" + "slices" "strings" + "sync" "time" "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/google/uuid" "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/types/query" @@ -35,13 +36,14 @@ type chainReader struct { lggr logger.Logger lp logpoller.LogPoller client evmclient.Client - contractBindings contractBindings + contractBindings bindings parsed *parsedTypes codec commontypes.RemoteCodec commonservices.StateMachine } var _ ChainReaderService = (*chainReader)(nil) +var _ commontypes.ContractTypeProvider = &chainReader{} // NewChainReaderService is a constructor for ChainReader, returns nil if there is any error // Note that the ChainReaderService returned does not support anonymous events. @@ -50,7 +52,7 @@ func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller lggr: lggr.Named("ChainReader"), lp: lp, client: client, - contractBindings: contractBindings{}, + contractBindings: bindings{}, parsed: &parsedTypes{encoderDefs: map[string]types.CodecEntry{}, decoderDefs: map[string]types.CodecEntry{}}, } @@ -63,52 +65,48 @@ func NewChainReaderService(ctx context.Context, lggr logger.Logger, lp logpoller return nil, err } - err = cr.contractBindings.ForEach(ctx, func(b readBinding, c context.Context) error { - b.SetCodec(cr.codec) + err = cr.contractBindings.ForEach(ctx, func(c context.Context, cb *contractBinding) error { + for _, rb := range cb.readBindings { + rb.SetCodec(cr.codec) + } return nil }) return cr, err } -func (cr *chainReader) Name() string { return cr.lggr.Name() } - -var _ commontypes.ContractTypeProvider = &chainReader{} - -func (cr *chainReader) GetLatestValue(ctx context.Context, contractName, method string, params any, returnVal any) error { - b, err := cr.contractBindings.GetReadBinding(contractName, method) - if err != nil { - return err - } - - return b.GetLatestValue(ctx, params, returnVal) -} - -func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundContract) error { - return cr.contractBindings.Bind(ctx, bindings) -} - -func (cr *chainReader) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { - b, err := cr.contractBindings.GetReadBinding(contractName, filter.Key) - if err != nil { - return nil, err - } - - return b.QueryKey(ctx, filter, limitAndSort, sequenceDataType) -} - func (cr *chainReader) init(chainContractReaders map[string]types.ChainContractReader) error { for contractName, chainContractReader := range chainContractReaders { contractAbi, err := abi.JSON(strings.NewReader(chainContractReader.ContractABI)) if err != nil { - return err + return fmt.Errorf("failed to parse abi for contract: %s, err: %w", contractName, err) } + var eventSigsForContractFilter evmtypes.HashArray for typeName, chainReaderDefinition := range chainContractReader.Configs { switch chainReaderDefinition.ReadType { case types.Method: err = cr.addMethod(contractName, typeName, contractAbi, *chainReaderDefinition) case types.Event: + partOfContractCommonFilter := slices.Contains(chainContractReader.GenericEventNames, typeName) + if !partOfContractCommonFilter && !chainReaderDefinition.HasPollingFilter() { + return fmt.Errorf( + "%w: chain reader has no polling filter defined for contract: %s, event: %s", + commontypes.ErrInvalidConfig, contractName, typeName) + } + + eventOverridesContractFilter := chainReaderDefinition.HasPollingFilter() + if eventOverridesContractFilter && partOfContractCommonFilter { + return fmt.Errorf( + "%w: conflicting chain reader polling filter definitions for contract: %s event: %s, can't have polling filter defined both on contract and event level", + commontypes.ErrInvalidConfig, contractName, typeName) + } + + if !eventOverridesContractFilter && + !slices.Contains(eventSigsForContractFilter, contractAbi.Events[chainReaderDefinition.ChainSpecificName].ID) { + eventSigsForContractFilter = append(eventSigsForContractFilter, contractAbi.Events[chainReaderDefinition.ChainSpecificName].ID) + } + err = cr.addEvent(contractName, typeName, contractAbi, *chainReaderDefinition) default: return fmt.Errorf( @@ -116,34 +114,75 @@ func (cr *chainReader) init(chainContractReaders map[string]types.ChainContractR commontypes.ErrInvalidConfig, chainReaderDefinition.ReadType) } - if err != nil { return err } } + cr.contractBindings[contractName].pollingFilter = chainContractReader.PollingFilter.ToLPFilter(eventSigsForContractFilter) } return nil } +func (cr *chainReader) Name() string { return cr.lggr.Name() } + +// Start registers polling filters if contracts are already bound. func (cr *chainReader) Start(ctx context.Context) error { return cr.StartOnce("ChainReader", func() error { - return cr.contractBindings.ForEach(ctx, readBinding.Register) + return cr.contractBindings.ForEach(ctx, func(c context.Context, cb *contractBinding) error { + for _, rb := range cb.readBindings { + if err := rb.Register(ctx); err != nil { + return err + } + } + return cb.Register(ctx, cr.lp) + }) }) } +// Close unregisters polling filters for bound contracts. func (cr *chainReader) Close() error { return cr.StopOnce("ChainReader", func() error { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - return cr.contractBindings.ForEach(ctx, readBinding.Unregister) + return cr.contractBindings.ForEach(ctx, func(c context.Context, cb *contractBinding) error { + for _, rb := range cb.readBindings { + if err := rb.Unregister(ctx); err != nil { + return err + } + } + return cb.Unregister(ctx, cr.lp) + }) }) } func (cr *chainReader) Ready() error { return nil } + func (cr *chainReader) HealthReport() map[string]error { return map[string]error{cr.Name(): nil} } +func (cr *chainReader) GetLatestValue(ctx context.Context, contractName, method string, params any, returnVal any) error { + b, err := cr.contractBindings.GetReadBinding(contractName, method) + if err != nil { + return err + } + + return b.GetLatestValue(ctx, params, returnVal) +} + +func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundContract) error { + return cr.contractBindings.Bind(ctx, cr.lp, bindings) +} + +func (cr *chainReader) QueryKey(ctx context.Context, contractName string, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { + b, err := cr.contractBindings.GetReadBinding(contractName, filter.Key) + if err != nil { + return nil, err + } + + return b.QueryKey(ctx, filter, limitAndSort, sequenceDataType) +} + func (cr *chainReader) CreateContractType(contractName, itemType string, forEncoding bool) (any, error) { return cr.codec.CreateType(wrapItemType(contractName, itemType, forEncoding), forEncoding) } @@ -165,13 +204,6 @@ func (cr *chainReader) addMethod( return fmt.Errorf("%w: method %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) } - if len(chainReaderDefinition.EventInputFields) != 0 { - return fmt.Errorf( - "%w: method %s has event topic fields defined, but is not an event", - commontypes.ErrInvalidConfig, - chainReaderDefinition.ChainSpecificName) - } - cr.contractBindings.AddReadBinding(contractName, methodName, &methodBinding{ contractName: contractName, method: methodName, @@ -191,8 +223,13 @@ func (cr *chainReader) addEvent(contractName, eventName string, a abi.ABI, chain return fmt.Errorf("%w: event %s doesn't exist", commontypes.ErrInvalidConfig, chainReaderDefinition.ChainSpecificName) } - filterArgs, codecTopicInfo, indexArgNames := setupEventInput(event, chainReaderDefinition) - if err := verifyEventInputsUsed(chainReaderDefinition, indexArgNames); err != nil { + var inputFields []string + if chainReaderDefinition.EventDefinitions != nil { + inputFields = chainReaderDefinition.EventDefinitions.InputFields + } + + filterArgs, codecTopicInfo, indexArgNames := setupEventInput(event, inputFields) + if err := verifyEventIndexedInputsUsed(eventName, inputFields, indexArgNames); err != nil { return err } @@ -224,34 +261,48 @@ func (cr *chainReader) addEvent(contractName, eventName string, a abi.ABI, chain inputModifier: inputModifier, codecTopicInfo: codecTopicInfo, topics: make(map[string]topicDetail), - eventDataWords: chainReaderDefinition.GenericDataWordNames, - id: wrapItemType(contractName, eventName, false) + uuid.NewString(), + eventDataWords: make(map[string]uint8), confirmationsMapping: confirmations, } + if eventDefinitions := chainReaderDefinition.EventDefinitions; eventDefinitions != nil { + if eventDefinitions.PollingFilter != nil { + eb.filterRegisterer = &filterRegisterer{ + pollingFilter: eventDefinitions.PollingFilter.ToLPFilter(evmtypes.HashArray{a.Events[event.Name].ID}), + filterLock: sync.Mutex{}, + } + } + + if eventDefinitions.GenericDataWordNames != nil { + eb.eventDataWords = eventDefinitions.GenericDataWordNames + } + + cr.addQueryingReadBindings(contractName, eventDefinitions.GenericTopicNames, event.Inputs, eb) + } + cr.contractBindings.AddReadBinding(contractName, eventName, eb) - // set topic mappings for QueryKeys - for topicIndex, topic := range event.Inputs { - genericTopicName, ok := chainReaderDefinition.GenericTopicNames[topic.Name] + return cr.addDecoderDef(contractName, eventName, event.Inputs, chainReaderDefinition) +} + +// addQueryingReadBindings reuses the eventBinding and maps it to topic and dataWord keys used for QueryKey. +func (cr *chainReader) addQueryingReadBindings(contractName string, genericTopicNames map[string]string, eventInputs abi.Arguments, eb *eventBinding) { + // add topic readBindings for QueryKey + for topicIndex, topic := range eventInputs { + genericTopicName, ok := genericTopicNames[topic.Name] if ok { eb.topics[genericTopicName] = topicDetail{ Argument: topic, Index: uint64(topicIndex), } } - - // this way querying by key/s values comparison can find its bindings cr.contractBindings.AddReadBinding(contractName, genericTopicName, eb) } - // set data word mappings for QueryKeys + // add data word readBindings for QueryKey for genericDataWordName := range eb.eventDataWords { - // this way querying by key/s values comparison can find its bindings cr.contractBindings.AddReadBinding(contractName, genericDataWordName, eb) } - - return cr.addDecoderDef(contractName, eventName, event.Inputs, chainReaderDefinition) } func (cr *chainReader) getEventInput(def types.ChainReaderDefinition, contractName, eventName string) ( @@ -270,10 +321,10 @@ func (cr *chainReader) getEventInput(def types.ChainReaderDefinition, contractNa return inputInfo, inMod, nil } -func verifyEventInputsUsed(chainReaderDefinition types.ChainReaderDefinition, indexArgNames map[string]bool) error { - for _, value := range chainReaderDefinition.EventInputFields { +func verifyEventIndexedInputsUsed(eventName string, inputFields []string, indexArgNames map[string]bool) error { + for _, value := range inputFields { if !indexArgNames[abi.ToCamelCase(value)] { - return fmt.Errorf("%w: %s is not an indexed argument of event %s", commontypes.ErrInvalidConfig, value, chainReaderDefinition.ChainSpecificName) + return fmt.Errorf("%w: %s is not an indexed argument of event %s", commontypes.ErrInvalidConfig, value, eventName) } } return nil @@ -305,9 +356,9 @@ func (cr *chainReader) addDecoderDef(contractName, itemType string, outputs abi. return output.Init() } -func setupEventInput(event abi.Event, def types.ChainReaderDefinition) ([]abi.Argument, types.CodecEntry, map[string]bool) { +func setupEventInput(event abi.Event, inputFields []string) ([]abi.Argument, types.CodecEntry, map[string]bool) { topicFieldDefs := map[string]bool{} - for _, value := range def.EventInputFields { + for _, value := range inputFields { capFirstValue := abi.ToCamelCase(value) topicFieldDefs[capFirstValue] = true } diff --git a/core/services/relay/evm/chain_reader_test.go b/core/services/relay/evm/chain_reader_test.go index 4b1d76199a..1e32753bc5 100644 --- a/core/services/relay/evm/chain_reader_test.go +++ b/core/services/relay/evm/chain_reader_test.go @@ -1,455 +1,215 @@ package evm_test import ( - "crypto/ecdsa" + "context" "fmt" "math" "math/big" "os" - "reflect" "strconv" "testing" "time" - "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" - evmtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/smartcontractkit/libocr/commontypes" + "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "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/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "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/internal/testutils/pgtest" - "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/v2/core/services/relay/evm/evmtesting" //nolint common practice to import test mods with . ) -const ( - commonGasLimitOnEvms = uint64(4712388) - triggerWithDynamicTopic = "TriggeredEventWithDynamicTopic" - triggerWithAllTopics = "TriggeredWithFourTopics" -) - -func TestChainReaderInterfaceTests(t *testing.T) { - t.Parallel() - it := &chainReaderInterfaceTester{} - - RunChainReaderInterfaceTests(t, it) - RunChainReaderInterfaceTests(t, commontestutils.WrapChainReaderTesterForLoop(it)) - - t.Run("Dynamically typed topics can be used to filter and have type correct in return", func(t *testing.T) { - it.Setup(t) - - // bind event before firing it to avoid log poller race - ctx := testutils.Context(t) - cr := it.GetChainReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) - - anyString := "foo" - tx, err := it.evmTest.TriggerEventWithDynamicTopic(it.auth, anyString) - require.NoError(t, err) - it.sim.Commit() - it.incNonce() - it.awaitTx(t, tx) - - input := struct{ Field string }{Field: anyString} - tp := cr.(clcommontypes.ContractTypeProvider) - output, err := tp.CreateContractType(AnyContractName, triggerWithDynamicTopic, false) - require.NoError(t, err) - rOutput := reflect.Indirect(reflect.ValueOf(output)) - - require.Eventually(t, func() bool { - return cr.GetLatestValue(ctx, AnyContractName, triggerWithDynamicTopic, input, output) == nil - }, it.MaxWaitTimeForEvents(), time.Millisecond*10) - - assert.Equal(t, &anyString, rOutput.FieldByName("Field").Interface()) - topic, err := abi.MakeTopics([]any{anyString}) - require.NoError(t, err) - assert.Equal(t, &topic[0][0], rOutput.FieldByName("FieldHash").Interface()) - }) - - t.Run("Multiple topics can filter together", func(t *testing.T) { - it.Setup(t) - - // bind event before firing it to avoid log poller race - ctx := testutils.Context(t) - cr := it.GetChainReader(t) - require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) - - triggerFourTopics(t, it, int32(1), int32(2), int32(3)) - triggerFourTopics(t, it, int32(2), int32(2), int32(3)) - triggerFourTopics(t, it, int32(1), int32(3), int32(3)) - triggerFourTopics(t, it, int32(1), int32(2), int32(4)) - - var latest struct{ Field1, Field2, Field3 int32 } - params := struct{ Field1, Field2, Field3 int32 }{Field1: 1, Field2: 2, Field3: 3} - - require.Eventually(t, func() bool { - return cr.GetLatestValue(ctx, AnyContractName, triggerWithAllTopics, params, &latest) == nil - }, it.MaxWaitTimeForEvents(), time.Millisecond*10) - - assert.Equal(t, int32(1), latest.Field1) - assert.Equal(t, int32(2), latest.Field2) - assert.Equal(t, int32(3), latest.Field3) - }) -} - -func triggerFourTopics(t *testing.T, it *chainReaderInterfaceTester, i1, i2, i3 int32) { - tx, err := it.evmTest.ChainReaderTesterTransactor.TriggerWithFourTopics(it.auth, i1, i2, i3) - require.NoError(t, err) - require.NoError(t, err) - it.sim.Commit() - it.incNonce() - it.awaitTx(t, tx) -} - -type chainReaderInterfaceTester struct { - client client.Client - address string - address2 string - chainConfig types.ChainReaderConfig - auth *bind.TransactOpts - sim *backends.SimulatedBackend - pk *ecdsa.PrivateKey - evmTest *chain_reader_tester.ChainReaderTester - cr evm.ChainReaderService -} - -func (it *chainReaderInterfaceTester) MaxWaitTimeForEvents() time.Duration { - // From trial and error, when running on CI, sometimes the boxes get slow - maxWaitTime := time.Second * 20 - maxWaitTimeStr, ok := os.LookupEnv("MAX_WAIT_TIME_FOR_EVENTS_S") - if ok { - waitS, err := strconv.ParseInt(maxWaitTimeStr, 10, 64) - if err != nil { - fmt.Printf("Error parsing MAX_WAIT_TIME_FOR_EVENTS_S: %v, defaulting to %v\n", err, maxWaitTime) - } - maxWaitTime = time.Second * time.Duration(waitS) - } - - return maxWaitTime -} - -func (it *chainReaderInterfaceTester) Setup(t *testing.T) { - t.Cleanup(func() { - // DB may be closed by the test already, ignore errors - if it.cr != nil { - _ = it.cr.Close() - } - it.cr = nil - it.evmTest = nil - }) - - // can re-use the same chain for tests, just make new contract for each test - if it.client != nil { - it.deployNewContracts(t) - return - } - - it.setupChainNoClient(t) - - testStruct := CreateTestStruct(0, it) - - it.chainConfig = types.ChainReaderConfig{ - Contracts: map[string]types.ChainContractReader{ - AnyContractName: { - ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, - Configs: map[string]*types.ChainReaderDefinition{ - MethodTakingLatestParamsReturningTestStruct: { - ChainSpecificName: "getElementAtIndex", - OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, - }, - }, - MethodReturningUint64: { - ChainSpecificName: "getPrimitiveValue", - }, - DifferentMethodReturningUint64: { - ChainSpecificName: "getDifferentPrimitiveValue", - }, - MethodReturningUint64Slice: { - ChainSpecificName: "getSliceValue", - }, - EventName: { - ChainSpecificName: "Triggered", - ReadType: types.Event, - OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, +const commonGasLimitOnEvms = uint64(4712388) + +func TestChainReaderEventsInitValidation(t *testing.T) { + tests := []struct { + name string + chainContractReaders map[string]types.ChainContractReader + expectedError error + }{ + { + name: "Invalid ABI", + chainContractReaders: map[string]types.ChainContractReader{ + "InvalidContract": { + ContractABI: "{invalid json}", + Configs: map[string]*types.ChainReaderDefinition{}, + }, + }, + expectedError: fmt.Errorf("failed to parse abi"), + }, + { + name: "Conflicting polling filter definitions", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithConflict": { + ContractABI: "[]", + Configs: map[string]*types.ChainReaderDefinition{ + "EventWithConflict": { + ChainSpecificName: "EventName", + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + PollingFilter: &types.PollingFilter{}, + }, }, - ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, }, - EventWithFilterName: { - ChainSpecificName: "Triggered", - ReadType: types.Event, - EventInputFields: []string{"Field"}, - ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{"EventWithConflict"}, }, - triggerWithDynamicTopic: { - ChainSpecificName: triggerWithDynamicTopic, - ReadType: types.Event, - EventInputFields: []string{"fieldHash"}, - InputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{Fields: map[string]string{"FieldHash": "Field"}}, + }, + }, + expectedError: fmt.Errorf( + "%w: conflicting chain reader polling filter definitions for contract: %s event: %s, can't have polling filter defined both on contract and event level", + clcommontypes.ErrInvalidConfig, "ContractWithConflict", "EventWithConflict"), + }, + { + name: "No polling filter defined", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithNoFilter": { + ContractABI: "[]", + Configs: map[string]*types.ChainReaderDefinition{ + "EventWithNoFilter": { + ChainSpecificName: "EventName", + ReadType: types.Event, }, - ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, - }, - triggerWithAllTopics: { - ChainSpecificName: triggerWithAllTopics, - ReadType: types.Event, - EventInputFields: []string{"Field1", "Field2", "Field3"}, - ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, }, - MethodReturningSeenStruct: { - ChainSpecificName: "returnSeen", - InputModifications: codec.ModifiersConfig{ - &codec.HardCodeModifierConfig{ - OnChainValues: map[string]any{ - "BigField": testStruct.BigField.String(), - "Account": hexutil.Encode(testStruct.Account), - }, - }, - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, - }, - OutputModifications: codec.ModifiersConfig{ - &codec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": anyExtraValue}}, - &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + }, + }, + expectedError: fmt.Errorf( + "%w: chain reader has no polling filter defined for contract: %s, event: %s", + clcommontypes.ErrInvalidConfig, "ContractWithNoFilter", "EventWithNoFilter"), + }, + { + name: "Invalid chain reader definition read type", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithInvalidReadType": { + ContractABI: "[]", + Configs: map[string]*types.ChainReaderDefinition{ + "InvalidReadType": { + ChainSpecificName: "InvalidName", + ReadType: types.ReadType(2), }, }, }, }, - AnySecondContractName: { - ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, - Configs: map[string]*types.ChainReaderDefinition{ - MethodReturningUint64: { - ChainSpecificName: "getDifferentPrimitiveValue", + expectedError: fmt.Errorf( + "%w: invalid chain reader definition read type", + clcommontypes.ErrInvalidConfig), + }, + { + name: "Event not present in ABI", + chainContractReaders: map[string]types.ChainContractReader{ + "ContractWithConflict": { + ContractABI: "[{\"anonymous\":false,\"inputs\":[],\"name\":\"WrongEvent\",\"type\":\"event\"}]", + Configs: map[string]*types.ChainReaderDefinition{ + "SomeEvent": { + ChainSpecificName: "EventName", + ReadType: types.Event, + }, + }, + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{"SomeEvent"}, }, }, }, + expectedError: fmt.Errorf( + "%w: event %s doesn't exist", + clcommontypes.ErrInvalidConfig, "EventName"), }, } - it.client = client.NewSimulatedBackendClient(t, it.sim, big.NewInt(1337)) - it.deployNewContracts(t) -} - -func (it *chainReaderInterfaceTester) Name() string { - return "EVM" -} - -func (it *chainReaderInterfaceTester) GetAccountBytes(i int) []byte { - account := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - account[i%20] += byte(i) - account[(i+3)%20] += byte(i + 3) - return account[:] -} - -func (it *chainReaderInterfaceTester) GetChainReader(t *testing.T) clcommontypes.ContractReader { - ctx := testutils.Context(t) - if it.cr != nil { - return it.cr - } - lggr := logger.NullLogger - db := pgtest.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 4, - BackfillBatchSize: 1, - RpcBatchSize: 1, - KeepFinalizedBlocksDepth: 10000, + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := evm.NewChainReaderService(testutils.Context(t), logger.NullLogger, nil, nil, types.ChainReaderConfig{Contracts: tt.chainContractReaders}) + require.Error(t, err) + if err != nil { + assert.Contains(t, err.Error(), tt.expectedError.Error()) + } + }) } - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.SimulatedChainID, db, lggr), it.client, lggr, lpOpts) - require.NoError(t, lp.Start(ctx)) - - // TODO uncomment this after this is fixed BCF-3242 - //chain := mocks.NewChain(t) - //chain.Mock.On("LogPoller").Return(lp) - //chain.Mock.On("ID").Return(it.client.ConfiguredChainID()) - // - //keyStore := cltest.NewKeyStore(t, db) - //relayer, err := evm.NewRelayer(lggr, chain, evm.RelayerOpts{DS: db, CSAETHKeystore: keyStore, CapabilitiesRegistry: capabilities.NewRegistry(lggr)}) - //require.NoError(t, err) - // - //cfgBytes, err := cbor.Marshal(it.chainConfig) - //require.NoError(t, err) - //cr, err := relayer.NewContractReader(cfgBytes) - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, it.client, it.chainConfig) - require.NoError(t, err) - require.NoError(t, cr.Start(ctx)) - it.cr = cr - return cr } -func (it *chainReaderInterfaceTester) SetLatestValue(t *testing.T, testStruct *TestStruct) { - it.sendTxWithTestStruct(t, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).AddTestStruct) -} - -func (it *chainReaderInterfaceTester) TriggerEvent(t *testing.T, testStruct *TestStruct) { - it.sendTxWithTestStruct(t, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).TriggerEvent) -} - -func (it *chainReaderInterfaceTester) GetBindings(_ *testing.T) []clcommontypes.BoundContract { - return []clcommontypes.BoundContract{ - {Name: AnyContractName, Address: it.address, Pending: true}, - {Name: AnySecondContractName, Address: it.address2, Pending: true}, - } -} - -type testStructFn = func(*chain_reader_tester.ChainReaderTesterTransactor, *bind.TransactOpts, int32, string, uint8, [32]uint8, common.Address, []common.Address, *big.Int, chain_reader_tester.MidLevelTestStruct) (*evmtypes.Transaction, error) - -func (it *chainReaderInterfaceTester) sendTxWithTestStruct(t *testing.T, testStruct *TestStruct, fn testStructFn) { - tx, err := fn( - &it.evmTest.ChainReaderTesterTransactor, - it.auth, - *testStruct.Field, - testStruct.DifferentField, - uint8(testStruct.OracleID), - convertOracleIDs(testStruct.OracleIDs), - common.Address(testStruct.Account), - convertAccounts(testStruct.Accounts), - testStruct.BigField, - midToInternalType(testStruct.NestedStruct), - ) - require.NoError(t, err) - it.sim.Commit() - it.incNonce() - it.awaitTx(t, tx) +func TestChainReader(t *testing.T) { + t.Parallel() + it := &EVMChainReaderInterfaceTester[*testing.T]{Helper: &helper{}} + // add new subtests here so that it can be run on real chains too + RunChainReaderEvmTests(t, it) + RunChainReaderInterfaceTests[*testing.T](t, commontestutils.WrapChainReaderTesterForLoop(it)) } -func convertOracleIDs(oracleIDs [32]commontypes.OracleID) [32]byte { - convertedIds := [32]byte{} - for i, id := range oracleIDs { - convertedIds[i] = byte(id) - } - return convertedIds +type helper struct { + sim *backends.SimulatedBackend + auth *bind.TransactOpts } -func convertAccounts(accounts [][]byte) []common.Address { - convertedAccounts := make([]common.Address, len(accounts)) - for i, a := range accounts { - convertedAccounts[i] = common.Address(a) - } - return convertedAccounts +func (h *helper) GasPriceBufferPercent() int64 { + return 0 } -func (it *chainReaderInterfaceTester) setupChainNoClient(t require.TestingT) { +func (h *helper) SetupAuth(t *testing.T) *bind.TransactOpts { privateKey, err := crypto.GenerateKey() require.NoError(t, err) - it.pk = privateKey - it.auth, err = bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) + h.auth, err = bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) require.NoError(t, err) - it.sim = backends.NewSimulatedBackend(core.GenesisAlloc{it.auth.From: {Balance: big.NewInt(math.MaxInt64)}}, commonGasLimitOnEvms*5000) - it.sim.Commit() + h.Backend() + h.Commit() + return h.auth } -func (it *chainReaderInterfaceTester) deployNewContracts(t *testing.T) { - it.address = it.deployNewContract(t) - it.address2 = it.deployNewContract(t) -} - -func (it *chainReaderInterfaceTester) deployNewContract(t *testing.T) string { - ctx := testutils.Context(t) - gasPrice, err := it.sim.SuggestGasPrice(ctx) - require.NoError(t, err) - it.auth.GasPrice = gasPrice - - // 105528 was in the error: gas too low: have 0, want 105528 - // Not sure if there's a better way to get it. - it.auth.GasLimit = 10552800 - - address, tx, ts, err := chain_reader_tester.DeployChainReaderTester(it.auth, it.sim) - - require.NoError(t, err) - it.sim.Commit() - if it.evmTest == nil { - it.evmTest = ts +func (h *helper) Backend() bind.ContractBackend { + if h.sim == nil { + h.sim = backends.NewSimulatedBackend( + core.GenesisAlloc{h.auth.From: {Balance: big.NewInt(math.MaxInt64)}}, commonGasLimitOnEvms*5000) } - it.incNonce() - it.awaitTx(t, tx) - return address.String() -} -func (it *chainReaderInterfaceTester) awaitTx(t *testing.T, tx *evmtypes.Transaction) { - ctx := testutils.Context(t) - receipt, err := it.sim.TransactionReceipt(ctx, tx.Hash()) - require.NoError(t, err) - require.Equal(t, evmtypes.ReceiptStatusSuccessful, receipt.Status) + return h.sim } -func (it *chainReaderInterfaceTester) incNonce() { - if it.auth.Nonce == nil { - it.auth.Nonce = big.NewInt(1) - } else { - it.auth.Nonce = it.auth.Nonce.Add(it.auth.Nonce, big.NewInt(1)) - } +func (h *helper) Commit() { + h.sim.Commit() } -func getAccounts(first TestStruct) []common.Address { - accountBytes := make([]common.Address, len(first.Accounts)) - for i, account := range first.Accounts { - accountBytes[i] = common.Address(account) - } - return accountBytes +func (h *helper) Client(t *testing.T) client.Client { + return client.NewSimulatedBackendClient(t, h.sim, big.NewInt(1337)) } -func argsFromTestStruct(ts TestStruct) []any { - return []any{ - ts.Field, - ts.DifferentField, - uint8(ts.OracleID), - getOracleIDs(ts), - common.Address(ts.Account), - getAccounts(ts), - ts.BigField, - midToInternalType(ts.NestedStruct), - } +func (h *helper) ChainID() *big.Int { + return testutils.SimulatedChainID } -func getOracleIDs(first TestStruct) [32]byte { - oracleIDs := [32]byte{} - for i, oracleID := range first.OracleIDs { - oracleIDs[i] = byte(oracleID) - } - return oracleIDs +func (h *helper) NewSqlxDB(t *testing.T) *sqlx.DB { + return pgtest.NewSqlxDB(t) } -func toInternalType(testStruct TestStruct) chain_reader_tester.TestStruct { - return chain_reader_tester.TestStruct{ - Field: *testStruct.Field, - DifferentField: testStruct.DifferentField, - OracleId: byte(testStruct.OracleID), - OracleIds: convertOracleIDs(testStruct.OracleIDs), - Account: common.Address(testStruct.Account), - Accounts: convertAccounts(testStruct.Accounts), - BigField: testStruct.BigField, - NestedStruct: midToInternalType(testStruct.NestedStruct), - } +func (h *helper) Context(t *testing.T) context.Context { + return testutils.Context(t) } -func midToInternalType(m MidLevelTestStruct) chain_reader_tester.MidLevelTestStruct { - return chain_reader_tester.MidLevelTestStruct{ - FixedBytes: m.FixedBytes, - Inner: chain_reader_tester.InnerTestStruct{ - IntVal: int64(m.Inner.I), - S: m.Inner.S, - }, +func (h *helper) MaxWaitTimeForEvents() time.Duration { + // From trial and error, when running on CI, sometimes the boxes get slow + maxWaitTime := time.Second * 30 + maxWaitTimeStr, ok := os.LookupEnv("MAX_WAIT_TIME_FOR_EVENTS_S") + if ok { + waitS, err := strconv.ParseInt(maxWaitTimeStr, 10, 64) + if err != nil { + fmt.Printf("Error parsing MAX_WAIT_TIME_FOR_EVENTS_S: %v, defaulting to %v\n", err, maxWaitTime) + } + maxWaitTime = time.Second * time.Duration(waitS) } + + return maxWaitTime } diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index fa62297efc..d0e76526dc 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -8,18 +8,19 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" ) type ChainWriterService interface { @@ -30,11 +31,17 @@ type ChainWriterService interface { // Compile-time assertion that chainWriter implements the ChainWriterService interface. var _ ChainWriterService = (*chainWriter)(nil) -func NewChainWriterService(logger logger.Logger, client evmclient.Client, txm evmtxmgr.TxManager, config types.ChainWriterConfig) (ChainWriterService, error) { +func NewChainWriterService(logger logger.Logger, client evmclient.Client, txm evmtxmgr.TxManager, estimator gas.EvmFeeEstimator, config types.ChainWriterConfig) (ChainWriterService, error) { + if config.MaxGasPrice == nil { + return nil, fmt.Errorf("max gas price is required") + } + w := chainWriter{ - logger: logger, - client: client, - txm: txm, + logger: logger, + client: client, + txm: txm, + ge: estimator, + maxGasPrice: config.MaxGasPrice, sendStrategy: txmgr.NewSendEveryStrategy(), contracts: config.Contracts, @@ -60,9 +67,11 @@ func NewChainWriterService(logger logger.Logger, client evmclient.Client, txm ev type chainWriter struct { commonservices.StateMachine - logger logger.Logger - client evmclient.Client - txm evmtxmgr.TxManager + logger logger.Logger + client evmclient.Client + txm evmtxmgr.TxManager + ge gas.EvmFeeEstimator + maxGasPrice *assets.Wei sendStrategy txmgrtypes.TxStrategy contracts map[string]*types.ContractConfig @@ -76,7 +85,7 @@ type chainWriter struct { // Note: The codec that ChainWriter uses to encode the parameters for the contract ABI cannot handle // `nil` values, including for slices. Until the bug is fixed we need to ensure that there are no // `nil` values passed in the request. -func (w *chainWriter) SubmitTransaction(ctx context.Context, contract, method string, args any, transactionID uuid.UUID, toAddress string, meta *commontypes.TxMeta, value big.Int) error { +func (w *chainWriter) SubmitTransaction(ctx context.Context, contract, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { if !common.IsHexAddress(toAddress) { return fmt.Errorf("toAddress is not a valid ethereum address: %v", toAddress) } @@ -101,6 +110,11 @@ func (w *chainWriter) SubmitTransaction(ctx context.Context, contract, method st checker.CheckerType = txmgrtypes.TransmitCheckerType(methodConfig.Checker) } + v := big.NewInt(0) + if value != nil { + v = value + } + req := evmtxmgr.TxRequest{ FromAddress: methodConfig.FromAddress, ToAddress: common.HexToAddress(toAddress), @@ -109,6 +123,7 @@ func (w *chainWriter) SubmitTransaction(ctx context.Context, contract, method st Meta: &txmgrtypes.TxMeta[common.Address, common.Hash]{WorkflowExecutionID: meta.WorkflowExecutionID}, Strategy: w.sendStrategy, Checker: checker, + Value: *v, } _, err = w.txm.CreateTransaction(ctx, req) @@ -151,12 +166,46 @@ func (w *chainWriter) parseContracts() error { return nil } -func (w *chainWriter) GetTransactionStatus(ctx context.Context, transactionID uuid.UUID) (commontypes.TransactionStatus, error) { +func (w *chainWriter) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { return commontypes.Unknown, fmt.Errorf("not implemented") } +// GetFeeComponents the execution and data availability (L1Oracle) fees for the chain. +// Dynamic fees (introduced in EIP-1559) include a fee cap and a tip cap. If the dyanmic fee is not available, +// (if the chain doesn't support dynamic TXs) the legacy GasPrice is used. func (w *chainWriter) GetFeeComponents(ctx context.Context) (*commontypes.ChainFeeComponents, error) { - return nil, fmt.Errorf("not implemented") + if w.ge == nil { + return nil, fmt.Errorf("gas estimator not available") + } + + fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice) + if err != nil { + return nil, err + } + // Use legacy if no dynamic is available. + gasPrice := fee.Legacy.ToInt() + if fee.DynamicFeeCap != nil { + gasPrice = fee.DynamicFeeCap.ToInt() + } + if gasPrice == nil { + return nil, fmt.Errorf("dynamic fee and legacy gas price missing %+v", fee) + } + l1Oracle := w.ge.L1Oracle() + if l1Oracle == nil { + return &commontypes.ChainFeeComponents{ + ExecutionFee: gasPrice, + DataAvailabilityFee: big.NewInt(0), + }, nil + } + l1OracleFee, err := l1Oracle.GasPrice(ctx) + if err != nil { + return nil, err + } + + return &commontypes.ChainFeeComponents{ + ExecutionFee: gasPrice, + DataAvailabilityFee: big.NewInt(l1OracleFee.Int64()), + }, nil } func (w *chainWriter) Close() error { diff --git a/core/services/relay/evm/chain_writer_test.go b/core/services/relay/evm/chain_writer_test.go new file mode 100644 index 0000000000..9344279da6 --- /dev/null +++ b/core/services/relay/evm/chain_writer_test.go @@ -0,0 +1,164 @@ +package evm + +import ( + "fmt" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + rollupmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" +) + +func TestChainWriter(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := testutils.Context(t) + + txm := txmmocks.NewMockEvmTxManager(t) + client := evmclimocks.NewClient(t) + ge := gasmocks.NewEvmFeeEstimator(t) + l1Oracle := rollupmocks.NewL1Oracle(t) + + chainWriterConfig := newBaseChainWriterConfig() + cw, err := NewChainWriterService(lggr, client, txm, ge, chainWriterConfig) + + require.NoError(t, err) + + t.Run("Initialization", func(t *testing.T) { + t.Run("Fails with invalid ABI", func(t *testing.T) { + baseConfig := newBaseChainWriterConfig() + invalidAbiConfig := modifyChainWriterConfig(baseConfig, func(cfg *relayevmtypes.ChainWriterConfig) { + cfg.Contracts["forwarder"].ContractABI = "" + }) + _, err = NewChainWriterService(lggr, client, txm, ge, invalidAbiConfig) + require.Error(t, err) + }) + + t.Run("Fails with invalid method names", func(t *testing.T) { + baseConfig := newBaseChainWriterConfig() + invalidMethodNameConfig := modifyChainWriterConfig(baseConfig, func(cfg *relayevmtypes.ChainWriterConfig) { + cfg.Contracts["forwarder"].Configs["report"].ChainSpecificName = "" + }) + _, err = NewChainWriterService(lggr, client, txm, ge, invalidMethodNameConfig) + require.Error(t, err) + }) + }) + + t.Run("SubmitTransaction", func(t *testing.T) { + // TODO: implement + }) + + t.Run("GetFeeComponents", func(t *testing.T) { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + Legacy: assets.NewWei(big.NewInt(1000000001)), + DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), + DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), + }, uint64(0), nil).Twice() + + l1Oracle.On("GasPrice", mock.Anything).Return(assets.NewWei(big.NewInt(1000000004)), nil).Once() + ge.On("L1Oracle", mock.Anything).Return(l1Oracle).Once() + var feeComponents *types.ChainFeeComponents + t.Run("Returns valid FeeComponents", func(t *testing.T) { + feeComponents, err = cw.GetFeeComponents(ctx) + require.NoError(t, err) + assert.Equal(t, big.NewInt(1000000002), feeComponents.ExecutionFee) + assert.Equal(t, big.NewInt(1000000004), feeComponents.DataAvailabilityFee) + }) + + ge.On("L1Oracle", mock.Anything).Return(nil).Twice() + + t.Run("Returns valid FeeComponents with no L1Oracle", func(t *testing.T) { + feeComponents, err = cw.GetFeeComponents(ctx) + require.NoError(t, err) + assert.Equal(t, big.NewInt(1000000002), feeComponents.ExecutionFee) + assert.Equal(t, big.NewInt(0), feeComponents.DataAvailabilityFee) + }) + + t.Run("Returns Legacy Fee in absence of Dynamic Fee", func(t *testing.T) { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + Legacy: assets.NewWei(big.NewInt(1000000001)), + DynamicFeeCap: nil, + DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), + }, uint64(0), nil).Once() + feeComponents, err = cw.GetFeeComponents(ctx) + require.NoError(t, err) + assert.Equal(t, big.NewInt(1000000001), feeComponents.ExecutionFee) + assert.Equal(t, big.NewInt(0), feeComponents.DataAvailabilityFee) + }) + + t.Run("Fails when neither legacy or dynamic fee is available", func(t *testing.T) { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + Legacy: nil, + DynamicFeeCap: nil, + DynamicTipCap: nil, + }, uint64(0), nil).Once() + + _, err = cw.GetFeeComponents(ctx) + require.Error(t, err) + }) + + t.Run("Fails when GetFee returns an error", func(t *testing.T) { + expectedErr := fmt.Errorf("GetFee error") + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + Legacy: nil, + DynamicFeeCap: nil, + DynamicTipCap: nil, + }, uint64(0), expectedErr).Once() + _, err = cw.GetFeeComponents(ctx) + require.Equal(t, expectedErr, err) + }) + + t.Run("Fails when L1Oracle returns error", func(t *testing.T) { + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + Legacy: assets.NewWei(big.NewInt(1000000001)), + DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), + DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), + }, uint64(0), nil).Once() + ge.On("L1Oracle", mock.Anything).Return(l1Oracle).Once() + + expectedErr := fmt.Errorf("l1Oracle error") + l1Oracle.On("GasPrice", mock.Anything).Return(nil, expectedErr).Once() + _, err = cw.GetFeeComponents(ctx) + require.Equal(t, expectedErr, err) + }) + }) +} + +// Helper functions to remove redundant creation of configs +func newBaseChainWriterConfig() relayevmtypes.ChainWriterConfig { + return relayevmtypes.ChainWriterConfig{ + Contracts: map[string]*relayevmtypes.ContractConfig{ + "forwarder": { + // TODO: Use generic ABI / test contract rather than a keystone specific one + ContractABI: forwarder.KeystoneForwarderABI, + Configs: map[string]*relayevmtypes.ChainWriterDefinition{ + "report": { + ChainSpecificName: "report", + Checker: "simulate", + FromAddress: testutils.NewAddress(), + GasLimit: 200_000, + }, + }, + }, + }, + MaxGasPrice: assets.NewWeiI(1000000000000), + } +} + +func modifyChainWriterConfig(baseConfig relayevmtypes.ChainWriterConfig, modifyFn func(*relayevmtypes.ChainWriterConfig)) relayevmtypes.ChainWriterConfig { + modifiedConfig := baseConfig + modifyFn(&modifiedConfig) + return modifiedConfig +} diff --git a/core/services/relay/evm/codec.go b/core/services/relay/evm/codec.go index a87976da54..9636996c2a 100644 --- a/core/services/relay/evm/codec.go +++ b/core/services/relay/evm/codec.go @@ -29,7 +29,13 @@ import ( // SliceToArrayVerifySizeHook verifies that slices have the correct size when converting to an array // sizeVerifyBigIntHook allows our custom types that verify the number fits in the on-chain type to be converted as-if // it was a *big.Int -var evmDecoderHooks = []mapstructure.DecodeHookFunc{decodeAccountAndAllowArraySliceHook, codec.BigIntHook, codec.SliceToArrayVerifySizeHook, sizeVerifyBigIntHook} +var evmDecoderHooks = []mapstructure.DecodeHookFunc{ + decodeAccountAndAllowArraySliceHook, + codec.BigIntHook, + codec.SliceToArrayVerifySizeHook, + sizeVerifyBigIntHook, + codec.NumberHook, +} // NewCodec creates a new [commontypes.RemoteCodec] for EVM. // Note that names in the ABI are converted to Go names using [abi.ToCamelCase], diff --git a/core/services/relay/evm/codec_test.go b/core/services/relay/evm/codec_test.go index 0773b27410..638a9afd70 100644 --- a/core/services/relay/evm/codec_test.go +++ b/core/services/relay/evm/codec_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" @@ -20,6 +21,7 @@ import ( "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" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -32,6 +34,33 @@ func TestCodec(t *testing.T) { anyN := 10 c := tester.GetCodec(t) + t.Run("Decode works with multiple unnamed return values", func(t *testing.T) { + encode := &struct { + F0 int32 + F1 int32 + }{F0: 1, F1: 2} + codecName := "my_codec" + evmEncoderConfig := `[{"Name":"","Type":"int32"},{"Name":"","Type":"int32"}]` + + codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ + codecName: {TypeABI: evmEncoderConfig}, + }} + c, err := evm.NewCodec(codecConfig) + require.NoError(t, err) + + result, err := c.Encode(testutils.Context(t), encode, codecName) + require.NoError(t, err) + + decode := &struct { + F0 int32 + F1 int32 + }{} + err = c.Decode(testutils.Context(t), result, decode, codecName) + require.NoError(t, err) + require.Equal(t, encode.F0, decode.F0) + require.Equal(t, encode.F1, decode.F1) + }) + t.Run("GetMaxEncodingSize delegates to GetMaxSize", func(t *testing.T) { actual, err := c.GetMaxEncodingSize(testutils.Context(t), anyN, sizeItemType) assert.NoError(t, err) @@ -167,7 +196,7 @@ func (it *codecInterfaceTester) EncodeFields(t *testing.T, request *EncodeReques func (it *codecInterfaceTester) GetCodec(t *testing.T) commontypes.Codec { codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{}} - testStruct := CreateTestStruct(0, it) + testStruct := CreateTestStruct[*testing.T](0, it) for k, v := range codecDefs { defBytes, err := json.Marshal(v) require.NoError(t, err) @@ -215,13 +244,13 @@ func encodeFieldsOnSliceOrArray(t *testing.T, request *EncodeRequest) []byte { switch request.TestOn { case TestItemArray1Type: - args[0] = [1]chain_reader_tester.TestStruct{toInternalType(request.TestStructs[0])} + args[0] = [1]chain_reader_tester.TestStruct{evmtesting.ToInternalType(request.TestStructs[0])} case TestItemArray2Type: - args[0] = [2]chain_reader_tester.TestStruct{toInternalType(request.TestStructs[0]), toInternalType(request.TestStructs[1])} + args[0] = [2]chain_reader_tester.TestStruct{evmtesting.ToInternalType(request.TestStructs[0]), evmtesting.ToInternalType(request.TestStructs[1])} default: tmp := make([]chain_reader_tester.TestStruct, len(request.TestStructs)) for i, ts := range request.TestStructs { - tmp[i] = toInternalType(ts) + tmp[i] = evmtesting.ToInternalType(ts) } args[0] = tmp } @@ -300,3 +329,32 @@ func parseDefs(t *testing.T) map[string]abi.Arguments { require.NoError(t, json.Unmarshal(bytes, &results)) return results } + +func getAccounts(first TestStruct) []common.Address { + accountBytes := make([]common.Address, len(first.Accounts)) + for i, account := range first.Accounts { + accountBytes[i] = common.Address(account) + } + return accountBytes +} + +func getOracleIDs(first TestStruct) [32]byte { + oracleIDs := [32]byte{} + for i, oracleID := range first.OracleIDs { + oracleIDs[i] = byte(oracleID) + } + return oracleIDs +} + +func argsFromTestStruct(ts TestStruct) []any { + return []any{ + ts.Field, + ts.DifferentField, + uint8(ts.OracleID), + getOracleIDs(ts), + common.Address(ts.Account), + getAccounts(ts), + ts.BigField, + evmtesting.MidToInternalType(ts.NestedStruct), + } +} diff --git a/core/services/relay/evm/contract_binding.go b/core/services/relay/evm/contract_binding.go new file mode 100644 index 0000000000..da2d7ed9bd --- /dev/null +++ b/core/services/relay/evm/contract_binding.go @@ -0,0 +1,100 @@ +package evm + +import ( + "context" + "fmt" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" + + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +type filterRegisterer struct { + pollingFilter logpoller.Filter + filterLock sync.Mutex + // registerCalled is used to determine if Register was called during Chain Reader service Start. + // This is done to avoid calling Register while the service is not running because log poller is most likely also not running. + registerCalled bool +} + +// contractBinding stores read bindings and manages the common contract event filter. +type contractBinding struct { + name string + // filterRegisterer is used to manage polling filter registration for the common contract filter. + // The common contract filter should be used by events that share filtering args. + filterRegisterer + // key is read name method, event or event keys used for queryKey. + readBindings map[string]readBinding + // bound determines if address is set to the contract binding. + bound bool + bindLock sync.Mutex +} + +// Bind binds contract addresses to contract binding and registers the common contract polling filter. +func (cb *contractBinding) Bind(ctx context.Context, lp logpoller.LogPoller, boundContract commontypes.BoundContract) error { + // it's enough to just lock bound here since Register/Unregister are only called from here and from Start/Close + // even if they somehow happen at the same time it will be fine because of filter lock and hasFilter check + cb.bindLock.Lock() + defer cb.bindLock.Unlock() + + if cb.bound { + // we are changing contract address reference, so we need to unregister old filter it exists + if err := cb.Unregister(ctx, lp); err != nil { + return err + } + } + + cb.pollingFilter.Addresses = evmtypes.AddressArray{common.HexToAddress(boundContract.Address)} + cb.pollingFilter.Name = logpoller.FilterName(boundContract.Name+"."+uuid.NewString(), boundContract.Address) + cb.bound = true + + if cb.registerCalled { + return cb.Register(ctx, lp) + } + + return nil +} + +// Register registers the common contract filter. +func (cb *contractBinding) Register(ctx context.Context, lp logpoller.LogPoller) error { + cb.filterLock.Lock() + defer cb.filterLock.Unlock() + + cb.registerCalled = true + // can't be true before filters params are set so there is no race with a bad filter outcome + if !cb.bound { + return nil + } + + if len(cb.pollingFilter.EventSigs) > 0 && !lp.HasFilter(cb.pollingFilter.Name) { + if err := lp.RegisterFilter(ctx, cb.pollingFilter); err != nil { + return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) + } + } + + return nil +} + +// Unregister unregisters the common contract filter. +func (cb *contractBinding) Unregister(ctx context.Context, lp logpoller.LogPoller) error { + cb.filterLock.Lock() + defer cb.filterLock.Unlock() + + if !cb.bound { + return nil + } + + if !lp.HasFilter(cb.pollingFilter.Name) { + return nil + } + + if err := lp.UnregisterFilter(ctx, cb.pollingFilter.Name); err != nil { + return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) + } + + return nil +} diff --git a/core/services/relay/evm/decoder.go b/core/services/relay/evm/decoder.go index f16875d80f..fdecf00202 100644 --- a/core/services/relay/evm/decoder.go +++ b/core/services/relay/evm/decoder.go @@ -18,7 +18,13 @@ type decoder struct { var _ commontypes.Decoder = &decoder{} -func (m *decoder) Decode(_ context.Context, raw []byte, into any, itemType string) error { +func (m *decoder) Decode(_ context.Context, raw []byte, into any, itemType string) (err error) { + defer func() { + // unexpected, but reflection can panic + if r := recover(); r != nil { + err = fmt.Errorf("%w: %v", commontypes.ErrInvalidType, r) + } + }() info, ok := m.Definitions[itemType] if !ok { return fmt.Errorf("%w: cannot find definition for %s", commontypes.ErrInvalidType, itemType) diff --git a/core/services/relay/evm/event_binding.go b/core/services/relay/evm/event_binding.go index f7f628f6bd..a3f1fa9d6a 100644 --- a/core/services/relay/evm/event_binding.go +++ b/core/services/relay/evm/event_binding.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -21,16 +22,19 @@ import ( ) type eventBinding struct { - address common.Address - contractName string - eventName string - lp logpoller.LogPoller - hash common.Hash - codec commontypes.RemoteCodec - pending bool + address common.Address + contractName string + eventName string + lp logpoller.LogPoller + // filterRegisterer in eventBinding is to be used as an override for lp filter defined in the contract binding. + // If filterRegisterer is nil, this event should be registered with the lp filter defined in the contract binding. + *filterRegisterer + hash common.Hash + codec commontypes.RemoteCodec + pending bool + // bound determines if address is set to the contract binding. bound bool - registerCalled bool - lock sync.Mutex + bindLock sync.Mutex inputInfo types.CodecEntry inputModifier codec.Modifier codecTopicInfo types.CodecEntry @@ -38,9 +42,8 @@ type eventBinding struct { topics map[string]topicDetail // eventDataWords maps a generic name to a word index // key is a predefined generic name for evm log event data word - // for eg. first evm data word(32bytes) of USDC log event is value so the key can be called value + // for e.g. first evm data word(32bytes) of USDC log event is value so the key can be called value eventDataWords map[string]uint8 - id string confirmationsMapping map[primitives.ConfidenceLevel]evmtypes.Confirmations } @@ -55,44 +58,90 @@ func (e *eventBinding) SetCodec(codec commontypes.RemoteCodec) { e.codec = codec } +func (e *eventBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { + // it's enough to just lock bound here since Register/Unregister are only called from here and from Start/Close + // even if they somehow happen at the same time it will be fine because of filter lock and hasFilter check + e.bindLock.Lock() + defer e.bindLock.Unlock() + + if e.bound { + // we are changing contract address reference, so we need to unregister old filter it exists + if err := e.Unregister(ctx); err != nil { + return err + } + } + + e.address = common.HexToAddress(binding.Address) + e.pending = binding.Pending + + // filterRegisterer isn't required here because the event can also be polled for by the contractBinding common filter. + if e.filterRegisterer != nil { + id := fmt.Sprintf("%s.%s.%s", e.contractName, e.eventName, uuid.NewString()) + e.pollingFilter.Name = logpoller.FilterName(id, e.address) + e.pollingFilter.Addresses = evmtypes.AddressArray{e.address} + e.bound = true + if e.registerCalled { + return e.Register(ctx) + } + } + e.bound = true + return nil +} + func (e *eventBinding) Register(ctx context.Context) error { - e.lock.Lock() - defer e.lock.Unlock() + if e.filterRegisterer == nil { + return nil + } + + e.filterLock.Lock() + defer e.filterLock.Unlock() e.registerCalled = true - if !e.bound || e.lp.HasFilter(e.id) { + // can't be true before filters params are set so there is no race with a bad filter outcome + if !e.bound { return nil } - if err := e.lp.RegisterFilter(ctx, logpoller.Filter{ - Name: e.id, - EventSigs: evmtypes.HashArray{e.hash}, - Addresses: evmtypes.AddressArray{e.address}, - }); err != nil { + if e.lp.HasFilter(e.pollingFilter.Name) { + return nil + } + + if err := e.lp.RegisterFilter(ctx, e.pollingFilter); err != nil { return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) } + return nil } func (e *eventBinding) Unregister(ctx context.Context) error { - e.lock.Lock() - defer e.lock.Unlock() + if e.filterRegisterer == nil { + return nil + } + + e.filterLock.Lock() + defer e.filterLock.Unlock() - if !e.lp.HasFilter(e.id) { + if !e.bound { return nil } - if err := e.lp.UnregisterFilter(ctx, e.id); err != nil { + if !e.lp.HasFilter(e.pollingFilter.Name) { + return nil + } + + if err := e.lp.UnregisterFilter(ctx, e.pollingFilter.Name); err != nil { return fmt.Errorf("%w: %w", commontypes.ErrInternal, err) } + return nil } func (e *eventBinding) GetLatestValue(ctx context.Context, params, into any) error { - if !e.bound { - return fmt.Errorf("%w: event not bound", commontypes.ErrInvalidType) + if err := e.validateBound(); err != nil { + return err } + // TODO BCF-3247 change GetLatestValue to use chain agnostic confidence levels confs := evmtypes.Finalized if e.pending { confs = evmtypes.Unconfirmed @@ -106,8 +155,8 @@ func (e *eventBinding) GetLatestValue(ctx context.Context, params, into any) err } func (e *eventBinding) QueryKey(ctx context.Context, filter query.KeyFilter, limitAndSort query.LimitAndSort, sequenceDataType any) ([]commontypes.Sequence, error) { - if !e.bound { - return nil, fmt.Errorf("%w: event not bound", commontypes.ErrInvalidType) + if err := e.validateBound(); err != nil { + return nil, err } remapped, err := e.remap(filter) @@ -135,17 +184,14 @@ func (e *eventBinding) QueryKey(ctx context.Context, filter query.KeyFilter, lim return e.decodeLogsIntoSequences(ctx, logs, sequenceDataType) } -func (e *eventBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { - if err := e.Unregister(ctx); err != nil { - return err - } - - e.address = common.HexToAddress(binding.Address) - e.pending = binding.Pending - e.bound = true - - if e.registerCalled { - return e.Register(ctx) +func (e *eventBinding) validateBound() error { + if !e.bound { + return fmt.Errorf( + "%w: event %s that belongs to contract: %s, not bound", + commontypes.ErrInvalidType, + e.eventName, + e.contractName, + ) } return nil } diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index abf7e06621..90b4abca2c 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -493,7 +493,7 @@ func (c *configWatcher) Start(ctx context.Context) error { defer cancel() c.lggr.Infow("starting replay for config", "fromBlock", c.fromBlock) if err := c.configPoller.Replay(ctx, int64(c.fromBlock)); err != nil { - c.lggr.Errorf("error replaying for config", "err", err) + c.lggr.Errorw("error replaying for config", "err", err) } else { c.lggr.Infow("completed replaying for config", "fromBlock", c.fromBlock) } diff --git a/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go b/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go new file mode 100644 index 0000000000..b9f141b2d0 --- /dev/null +++ b/core/services/relay/evm/evmtesting/chain_reader_interface_tester.go @@ -0,0 +1,349 @@ +package evmtesting + +import ( + "context" + "encoding/json" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/jmoiron/sqlx" + "github.com/smartcontractkit/libocr/commontypes" + + "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/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" + _ "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" // force binding for tx type + "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" + + evmtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +const ( + triggerWithDynamicTopic = "TriggeredEventWithDynamicTopic" + triggerWithAllTopics = "TriggeredWithFourTopics" +) + +type EVMChainReaderInterfaceTesterHelper[T TestingT[T]] interface { + SetupAuth(t T) *bind.TransactOpts + Client(t T) client.Client + Commit() + Backend() bind.ContractBackend + ChainID() *big.Int + Context(t T) context.Context + NewSqlxDB(t T) *sqlx.DB + MaxWaitTimeForEvents() time.Duration + GasPriceBufferPercent() int64 +} + +type EVMChainReaderInterfaceTester[T TestingT[T]] struct { + Helper EVMChainReaderInterfaceTesterHelper[T] + client client.Client + address string + address2 string + chainConfig types.ChainReaderConfig + auth *bind.TransactOpts + evmTest *chain_reader_tester.ChainReaderTester + cr evm.ChainReaderService + dirtyContracts bool +} + +func (it *EVMChainReaderInterfaceTester[T]) Setup(t T) { + t.Cleanup(func() { + // DB may be closed by the test already, ignore errors + if it.cr != nil { + _ = it.cr.Close() + } + it.cr = nil + + if it.dirtyContracts { + it.evmTest = nil + } + }) + + // can re-use the same chain for tests, just make new contract for each test + if it.client != nil { + it.deployNewContracts(t) + return + } + + it.auth = it.Helper.SetupAuth(t) + + testStruct := CreateTestStruct[T](0, it) + + it.chainConfig = types.ChainReaderConfig{ + Contracts: map[string]types.ChainContractReader{ + AnyContractName: { + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, + ContractPollingFilter: types.ContractPollingFilter{ + GenericEventNames: []string{EventName, EventWithFilterName}, + }, + Configs: map[string]*types.ChainReaderDefinition{ + MethodTakingLatestParamsReturningTestStruct: { + ChainSpecificName: "getElementAtIndex", + OutputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + }, + }, + MethodReturningUint64: { + ChainSpecificName: "getPrimitiveValue", + }, + DifferentMethodReturningUint64: { + ChainSpecificName: "getDifferentPrimitiveValue", + }, + MethodReturningUint64Slice: { + ChainSpecificName: "getSliceValue", + }, + EventName: { + ChainSpecificName: "Triggered", + ReadType: types.Event, + OutputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + }, + ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, + }, + EventWithFilterName: { + ChainSpecificName: "Triggered", + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{InputFields: []string{"Field"}}, + ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, + }, + triggerWithDynamicTopic: { + ChainSpecificName: triggerWithDynamicTopic, + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + InputFields: []string{"fieldHash"}, + // no specific reason for filter being defined here insted on contract level, + // this is just for test case variety + PollingFilter: &types.PollingFilter{}, + }, + InputModifications: codec.ModifiersConfig{ + &codec.RenameModifierConfig{Fields: map[string]string{"FieldHash": "Field"}}, + }, + ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, + }, + triggerWithAllTopics: { + ChainSpecificName: triggerWithAllTopics, + ReadType: types.Event, + EventDefinitions: &types.EventDefinitions{ + InputFields: []string{"Field1", "Field2", "Field3"}, + PollingFilter: &types.PollingFilter{}, + }, + ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, + }, + MethodReturningSeenStruct: { + ChainSpecificName: "returnSeen", + InputModifications: codec.ModifiersConfig{ + &codec.HardCodeModifierConfig{ + OnChainValues: map[string]any{ + "BigField": testStruct.BigField.String(), + "Account": hexutil.Encode(testStruct.Account), + }, + }, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + }, + OutputModifications: codec.ModifiersConfig{ + &codec.HardCodeModifierConfig{OffChainValues: map[string]any{"ExtraField": AnyExtraValue}}, + &codec.RenameModifierConfig{Fields: map[string]string{"NestedStruct.Inner.IntVal": "I"}}, + }, + }, + }, + }, + AnySecondContractName: { + ContractABI: chain_reader_tester.ChainReaderTesterMetaData.ABI, + Configs: map[string]*types.ChainReaderDefinition{ + MethodReturningUint64: { + ChainSpecificName: "getDifferentPrimitiveValue", + }, + }, + }, + }, + } + it.client = it.Helper.Client(t) + + it.deployNewContracts(t) +} + +func (it *EVMChainReaderInterfaceTester[T]) Name() string { + return "EVM" +} + +func (it *EVMChainReaderInterfaceTester[T]) GetAccountBytes(i int) []byte { + account := [20]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + account[i%20] += byte(i) + account[(i+3)%20] += byte(i + 3) + return account[:] +} + +func (it *EVMChainReaderInterfaceTester[T]) GetChainReader(t T) clcommontypes.ContractReader { + ctx := it.Helper.Context(t) + if it.cr != nil { + return it.cr + } + + lggr := logger.NullLogger + db := it.Helper.NewSqlxDB(t) + lpOpts := logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: 4, + BackfillBatchSize: 1, + RpcBatchSize: 1, + KeepFinalizedBlocksDepth: 10000, + } + lp := logpoller.NewLogPoller(logpoller.NewORM(it.Helper.ChainID(), db, lggr), it.client, lggr, lpOpts) + require.NoError(t, lp.Start(ctx)) + + // encode and decode the config to ensure the test covers type issues + confBytes, err := json.Marshal(it.chainConfig) + require.NoError(t, err) + + conf, err := types.ChainReaderConfigFromBytes(confBytes) + require.NoError(t, err) + + cr, err := evm.NewChainReaderService(ctx, lggr, lp, it.client, conf) + require.NoError(t, err) + require.NoError(t, cr.Start(ctx)) + it.cr = cr + return cr +} + +func (it *EVMChainReaderInterfaceTester[T]) SetLatestValue(t T, testStruct *TestStruct) { + it.sendTxWithTestStruct(t, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).AddTestStruct) +} + +func (it *EVMChainReaderInterfaceTester[T]) TriggerEvent(t T, testStruct *TestStruct) { + it.sendTxWithTestStruct(t, testStruct, (*chain_reader_tester.ChainReaderTesterTransactor).TriggerEvent) +} + +func (it *EVMChainReaderInterfaceTester[T]) GetBindings(_ T) []clcommontypes.BoundContract { + return []clcommontypes.BoundContract{ + {Name: AnyContractName, Address: it.address, Pending: true}, + {Name: AnySecondContractName, Address: it.address2, Pending: true}, + } +} + +type testStructFn = func(*chain_reader_tester.ChainReaderTesterTransactor, *bind.TransactOpts, int32, string, uint8, [32]uint8, common.Address, []common.Address, *big.Int, chain_reader_tester.MidLevelTestStruct) (*evmtypes.Transaction, error) + +func (it *EVMChainReaderInterfaceTester[T]) sendTxWithTestStruct(t T, testStruct *TestStruct, fn testStructFn) { + tx, err := fn( + &it.evmTest.ChainReaderTesterTransactor, + it.GetAuthWithGasSet(t), + *testStruct.Field, + testStruct.DifferentField, + uint8(testStruct.OracleID), + OracleIdsToBytes(testStruct.OracleIDs), + common.Address(testStruct.Account), + ConvertAccounts(testStruct.Accounts), + testStruct.BigField, + MidToInternalType(testStruct.NestedStruct), + ) + require.NoError(t, err) + it.Helper.Commit() + it.IncNonce() + it.AwaitTx(t, tx) + it.dirtyContracts = true +} + +func (it *EVMChainReaderInterfaceTester[T]) GetAuthWithGasSet(t T) *bind.TransactOpts { + gasPrice, err := it.client.SuggestGasPrice(it.Helper.Context(t)) + require.NoError(t, err) + extra := new(big.Int).Mul(gasPrice, big.NewInt(it.Helper.GasPriceBufferPercent())) + extra = extra.Div(extra, big.NewInt(100)) + it.auth.GasPrice = gasPrice.Add(gasPrice, extra) + return it.auth +} + +func (it *EVMChainReaderInterfaceTester[T]) IncNonce() { + if it.auth.Nonce == nil { + it.auth.Nonce = big.NewInt(1) + } else { + it.auth.Nonce = it.auth.Nonce.Add(it.auth.Nonce, big.NewInt(1)) + } +} + +func (it *EVMChainReaderInterfaceTester[T]) AwaitTx(t T, tx *evmtypes.Transaction) { + ctx := it.Helper.Context(t) + receipt, err := bind.WaitMined(ctx, it.client, tx) + require.NoError(t, err) + require.Equal(t, evmtypes.ReceiptStatusSuccessful, receipt.Status) +} + +func (it *EVMChainReaderInterfaceTester[T]) deployNewContracts(t T) { + // First test deploy both contracts, otherwise only deploy contracts if cleanup decides that we need to. + if it.address == "" { + it.address = it.deployNewContract(t) + it.address2 = it.deployNewContract(t) + } else if it.evmTest == nil { + it.address = it.deployNewContract(t) + it.dirtyContracts = false + } +} + +func (it *EVMChainReaderInterfaceTester[T]) deployNewContract(t T) string { + // 105528 was in the error: gas too low: have 0, want 105528 + // Not sure if there's a better way to get it. + it.auth.GasLimit = 10552800 + + address, tx, ts, err := chain_reader_tester.DeployChainReaderTester(it.GetAuthWithGasSet(t), it.Helper.Backend()) + require.NoError(t, err) + it.Helper.Commit() + if it.evmTest == nil { + it.evmTest = ts + } + + it.IncNonce() + it.AwaitTx(t, tx) + return address.String() +} + +func (it *EVMChainReaderInterfaceTester[T]) MaxWaitTimeForEvents() time.Duration { + return it.Helper.MaxWaitTimeForEvents() +} + +func OracleIdsToBytes(oracleIDs [32]commontypes.OracleID) [32]byte { + convertedIds := [32]byte{} + for i, id := range oracleIDs { + convertedIds[i] = byte(id) + } + return convertedIds +} + +func ConvertAccounts(accounts [][]byte) []common.Address { + convertedAccounts := make([]common.Address, len(accounts)) + for i, a := range accounts { + convertedAccounts[i] = common.Address(a) + } + return convertedAccounts +} + +func ToInternalType(testStruct TestStruct) chain_reader_tester.TestStruct { + return chain_reader_tester.TestStruct{ + Field: *testStruct.Field, + DifferentField: testStruct.DifferentField, + OracleId: byte(testStruct.OracleID), + OracleIds: OracleIdsToBytes(testStruct.OracleIDs), + Account: common.Address(testStruct.Account), + Accounts: ConvertAccounts(testStruct.Accounts), + BigField: testStruct.BigField, + NestedStruct: MidToInternalType(testStruct.NestedStruct), + } +} + +func MidToInternalType(m MidLevelTestStruct) chain_reader_tester.MidLevelTestStruct { + return chain_reader_tester.MidLevelTestStruct{ + FixedBytes: m.FixedBytes, + Inner: chain_reader_tester.InnerTestStruct{ + IntVal: int64(m.Inner.I), + S: m.Inner.S, + }, + } +} diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go new file mode 100644 index 0000000000..28bda5a09a --- /dev/null +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -0,0 +1,96 @@ +package evmtesting + +import ( + "math/big" + "reflect" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + 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/services/relay/evm" +) + +func RunChainReaderEvmTests[T TestingT[T]](t T, it *EVMChainReaderInterfaceTester[T]) { + RunChainReaderInterfaceTests[T](t, it) + + t.Run("Dynamically typed topics can be used to filter and have type correct in return", func(t T) { + it.Setup(t) + + anyString := "foo" + it.dirtyContracts = true + tx, err := it.evmTest.ChainReaderTesterTransactor.TriggerEventWithDynamicTopic(it.GetAuthWithGasSet(t), anyString) + require.NoError(t, err) + it.Helper.Commit() + it.IncNonce() + it.AwaitTx(t, tx) + ctx := it.Helper.Context(t) + + cr := it.GetChainReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + + input := struct{ Field string }{Field: anyString} + tp := cr.(clcommontypes.ContractTypeProvider) + output, err := tp.CreateContractType(AnyContractName, triggerWithDynamicTopic, false) + require.NoError(t, err) + rOutput := reflect.Indirect(reflect.ValueOf(output)) + + require.Eventually(t, func() bool { + return cr.GetLatestValue(ctx, AnyContractName, triggerWithDynamicTopic, input, output) == nil + }, it.MaxWaitTimeForEvents(), 100*time.Millisecond) + + assert.Equal(t, &anyString, rOutput.FieldByName("Field").Interface()) + topic, err := abi.MakeTopics([]any{anyString}) + require.NoError(t, err) + assert.Equal(t, &topic[0][0], rOutput.FieldByName("FieldHash").Interface()) + }) + + t.Run("Multiple topics can filter together", func(t T) { + it.Setup(t) + it.dirtyContracts = true + triggerFourTopics(t, it, int32(1), int32(2), int32(3)) + triggerFourTopics(t, it, int32(2), int32(2), int32(3)) + triggerFourTopics(t, it, int32(1), int32(3), int32(3)) + triggerFourTopics(t, it, int32(1), int32(2), int32(4)) + + ctx := it.Helper.Context(t) + cr := it.GetChainReader(t) + require.NoError(t, cr.Bind(ctx, it.GetBindings(t))) + var latest struct{ Field1, Field2, Field3 int32 } + params := struct{ Field1, Field2, Field3 int32 }{Field1: 1, Field2: 2, Field3: 3} + + time.Sleep(it.MaxWaitTimeForEvents()) + + require.NoError(t, cr.GetLatestValue(ctx, AnyContractName, triggerWithAllTopics, params, &latest)) + assert.Equal(t, int32(1), latest.Field1) + assert.Equal(t, int32(2), latest.Field2) + assert.Equal(t, int32(3), latest.Field3) + }) + + t.Run("Bind returns error on missing contract at address", func(t T) { + it.Setup(t) + + addr := common.BigToAddress(big.NewInt(42)) + reader := it.GetChainReader(t) + + ctx := it.Helper.Context(t) + err := reader.Bind(ctx, []clcommontypes.BoundContract{{Name: AnyContractName, Address: addr.Hex(), Pending: true}}) + + require.ErrorIs(t, err, evm.NoContractExistsError{Address: addr}) + }) +} + +func triggerFourTopics[T TestingT[T]](t T, it *EVMChainReaderInterfaceTester[T], i1, i2, i3 int32) { + tx, err := it.evmTest.ChainReaderTesterTransactor.TriggerWithFourTopics(it.GetAuthWithGasSet(t), i1, i2, i3) + require.NoError(t, err) + require.NoError(t, err) + it.Helper.Commit() + it.IncNonce() + it.AwaitTx(t, tx) +} diff --git a/core/services/relay/evm/functions/logpoller_wrapper.go b/core/services/relay/evm/functions/logpoller_wrapper.go index 4e37770f90..559b1ec33f 100644 --- a/core/services/relay/evm/functions/logpoller_wrapper.go +++ b/core/services/relay/evm/functions/logpoller_wrapper.go @@ -244,7 +244,7 @@ func (l *logPollerWrapper) LatestEvents(ctx context.Context) ([]evmRelayTypes.Or oracleRequest.Commitment.TimeoutTimestamp, ) if err != nil { - l.lggr.Errorw("LatestEvents: failed to pack commitment bytes, skipping", err) + l.lggr.Errorw("LatestEvents: failed to pack commitment bytes, skipping", "err", err) } resultsReq = append(resultsReq, evmRelayTypes.OracleRequest{ diff --git a/core/services/relay/evm/method_binding.go b/core/services/relay/evm/method_binding.go index 7484d17c3e..4f642bdab9 100644 --- a/core/services/relay/evm/method_binding.go +++ b/core/services/relay/evm/method_binding.go @@ -13,6 +13,14 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) +type NoContractExistsError struct { + Address common.Address +} + +func (e NoContractExistsError) Error() string { + return fmt.Sprintf("contract does not exist at address: %s", e.Address) +} + type methodBinding struct { address common.Address contractName string @@ -28,15 +36,30 @@ func (m *methodBinding) SetCodec(codec commontypes.RemoteCodec) { m.codec = codec } -func (m *methodBinding) Register(_ context.Context) error { +func (m *methodBinding) Bind(ctx context.Context, binding commontypes.BoundContract) error { + addr := common.HexToAddress(binding.Address) + + // check for contract byte code at the latest block and provided address + byteCode, err := m.client.CodeAt(ctx, addr, nil) + if err != nil { + return err + } + + if len(byteCode) == 0 { + return NoContractExistsError{Address: addr} + } + + m.address = addr + m.bound = true + return nil } -func (m *methodBinding) Unregister(_ context.Context) error { +func (m *methodBinding) Register(_ context.Context) error { return nil } -func (m *methodBinding) UnregisterAll(_ context.Context) error { +func (m *methodBinding) Unregister(_ context.Context) error { return nil } @@ -67,9 +90,3 @@ func (m *methodBinding) GetLatestValue(ctx context.Context, params, returnValue func (m *methodBinding) QueryKey(_ context.Context, _ query.KeyFilter, _ query.LimitAndSort, _ any) ([]commontypes.Sequence, error) { return nil, nil } - -func (m *methodBinding) Bind(_ context.Context, binding commontypes.BoundContract) error { - m.address = common.HexToAddress(binding.Address) - m.bound = true - return nil -} diff --git a/core/services/relay/evm/types/codec_entry.go b/core/services/relay/evm/types/codec_entry.go index b42bf9c0b0..38242c43a2 100644 --- a/core/services/relay/evm/types/codec_entry.go +++ b/core/services/relay/evm/types/codec_entry.go @@ -146,11 +146,13 @@ func (entry *codecEntry) Init() (err error) { } for { name = name + "_X" + arg.Name = name if !seenNames[name] { break } } } + args[i] = arg seenNames[name] = true native[i] = reflect.StructField{Name: name, Type: nativeArg} checked[i] = reflect.StructField{Name: name, Type: checkedArg} diff --git a/core/services/relay/evm/types/codec_entry_test.go b/core/services/relay/evm/types/codec_entry_test.go index da1d4cc22a..06b08fcecf 100644 --- a/core/services/relay/evm/types/codec_entry_test.go +++ b/core/services/relay/evm/types/codec_entry_test.go @@ -219,11 +219,15 @@ func TestCodecEntry(t *testing.T) { assert.NoError(t, entry.Init()) ct := entry.CheckedType() require.Equal(t, 2, ct.NumField()) + args := entry.Args() + require.Equal(t, 2, len(args)) f0 := ct.Field(0) assert.Equal(t, "F0", f0.Name) + assert.Equal(t, "F0", args[0].Name) assert.Equal(t, reflect.TypeOf((*int64)(nil)), f0.Type) f1 := ct.Field(1) assert.Equal(t, "F1", f1.Name) + assert.Equal(t, "F1", args[1].Name) assert.Equal(t, reflect.TypeOf((*int32)(nil)), f1.Type) }) @@ -237,11 +241,14 @@ func TestCodecEntry(t *testing.T) { assert.NoError(t, entry.Init()) ct := entry.CheckedType() require.Equal(t, 2, ct.NumField()) + args := entry.Args() + require.Equal(t, 2, len(args)) f0 := ct.Field(0) assert.Equal(t, "F1", f0.Name) assert.Equal(t, reflect.TypeOf((*int64)(nil)), f0.Type) f1 := ct.Field(1) assert.Equal(t, "F1_X", f1.Name) + assert.Equal(t, "F1_X", args[1].Name) assert.Equal(t, reflect.TypeOf((*int32)(nil)), f1.Type) }) diff --git a/core/services/relay/evm/types/types.go b/core/services/relay/evm/types/types.go index 873f58a9a0..35684e507a 100644 --- a/core/services/relay/evm/types/types.go +++ b/core/services/relay/evm/types/types.go @@ -18,13 +18,17 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types" - + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + evmtypes "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/store/models" ) type ChainWriterConfig struct { Contracts map[string]*ContractConfig SendStrategy txmgrtypes.TxStrategy + MaxGasPrice *assets.Wei } type ContractConfig struct { @@ -54,17 +58,59 @@ type CodecConfig struct { type ChainCodecConfig struct { TypeABI string `json:"typeAbi" toml:"typeABI"` - ModifierConfigs codec.ModifiersConfig `toml:"modifierConfigs,omitempty"` + ModifierConfigs codec.ModifiersConfig `json:"modifierConfigs,omitempty" toml:"modifierConfigs,omitempty"` +} + +type ContractPollingFilter struct { + GenericEventNames []string `json:"genericEventNames"` + PollingFilter `json:"pollingFilter"` +} + +type PollingFilter struct { + Topic2 evmtypes.HashArray `json:"topic2"` // list of possible values for topic2 + Topic3 evmtypes.HashArray `json:"topic3"` // list of possible values for topic3 + Topic4 evmtypes.HashArray `json:"topic4"` // list of possible values for topic4 + Retention models.Interval `json:"retention"` // maximum amount of time to retain logs + MaxLogsKept uint64 `json:"maxLogsKept"` // maximum number of logs to retain ( 0 = unlimited ) + LogsPerBlock uint64 `json:"logsPerBlock"` // rate limit ( maximum # of logs per block, 0 = unlimited ) +} + +func (f *PollingFilter) ToLPFilter(eventSigs evmtypes.HashArray) logpoller.Filter { + return logpoller.Filter{ + EventSigs: eventSigs, + Topic2: f.Topic2, + Topic3: f.Topic3, + Topic4: f.Topic4, + Retention: f.Retention.Duration(), + MaxLogsKept: f.MaxLogsKept, + LogsPerBlock: f.LogsPerBlock, + } } type ChainContractReader struct { - ContractABI string `json:"contractABI" toml:"contractABI"` + ContractABI string `json:"contractABI" toml:"contractABI"` + ContractPollingFilter `json:"contractPollingFilter,omitempty" toml:"contractPollingFilter,omitempty"` // key is genericName from config Configs map[string]*ChainReaderDefinition `json:"configs" toml:"configs"` } type ChainReaderDefinition chainReaderDefinitionFields +type EventDefinitions struct { + // GenericTopicNames helps QueryingKeys not rely on EVM specific topic names. Key is chain specific name, value is generic name. + // This helps us translate chain agnostic querying key "transfer-value" to EVM specific "evmTransferEvent-weiAmountTopic". + GenericTopicNames map[string]string `json:"genericTopicNames,omitempty"` + // key is a predefined generic name for evm log event data word + // for e.g. first evm data word(32bytes) of USDC log event is value so the key can be called value + GenericDataWordNames map[string]uint8 `json:"genericDataWordNames,omitempty"` + // InputFields allows you to choose which indexed fields are expected from the input + InputFields []string `json:"inputFields,omitempty"` + // PollingFilter should be defined on a contract level in ContractPollingFilter, + // unless event needs to override the contract level filter options. + // This will create a separate log poller filter for this event. + *PollingFilter `json:"pollingFilter,omitempty"` +} + // chainReaderDefinitionFields has the fields for ChainReaderDefinition but no methods. // This is necessary because package json recognizes the text encoding methods used for TOML, // and would infinitely recurse on itself. @@ -75,20 +121,16 @@ type chainReaderDefinitionFields struct { ReadType ReadType `json:"readType,omitempty"` InputModifications codec.ModifiersConfig `json:"inputModifications,omitempty"` OutputModifications codec.ModifiersConfig `json:"outputModifications,omitempty"` - - // EventInputFields allows you to choose which indexed fields are expected from the input - EventInputFields []string `json:"eventInputFields,omitempty"` - // GenericTopicNames helps QueryingKeys not rely on EVM specific topic names. Key is chain specific name, value is generic name. - // This helps us translate chain agnostic querying key "transfer-value" to EVM specific "evmTransferEvent-weiAmountTopic". - GenericTopicNames map[string]string `json:"genericTopicNames,omitempty"` - // key is a predefined generic name for evm log event data word - // for eg. first evm data word(32bytes) of USDC log event is value so the key can be called value - GenericDataWordNames map[string]uint8 `json:"genericDataWordNames,omitempty"` + EventDefinitions *EventDefinitions `json:"eventDefinitions,omitempty" toml:"eventDefinitions,omitempty"` // ConfidenceConfirmations is a mapping between a ConfidenceLevel and the confirmations associated. Confidence levels // should be valid float values. ConfidenceConfirmations map[string]int `json:"confidenceConfirmations,omitempty"` } +func (d *ChainReaderDefinition) HasPollingFilter() bool { + return d.EventDefinitions != nil && d.EventDefinitions.PollingFilter != nil +} + func (d *ChainReaderDefinition) MarshalText() ([]byte, error) { var b bytes.Buffer e := json.NewEncoder(&b) @@ -236,3 +278,19 @@ type LogPollerWrapper interface { // TODO (FUN-668): Remove from the LOOP interface and only use internally within the EVM relayer SubscribeToUpdates(ctx context.Context, name string, subscriber RouteUpdateSubscriber) } + +// ChainReaderConfigFromBytes function applies json decoding on provided bytes to return a +// valid ChainReaderConfig. If other unmarshaling or parsing techniques are required, place it +// here. +func ChainReaderConfigFromBytes(bts []byte) (ChainReaderConfig, error) { + decoder := json.NewDecoder(bytes.NewBuffer(bts)) + + decoder.UseNumber() + + var cfg ChainReaderConfig + if err := decoder.Decode(&cfg); err != nil { + return cfg, fmt.Errorf("failed to unmarshal chain reader config err: %s", err) + } + + return cfg, nil +} diff --git a/core/services/relay/evm/types/types_test.go b/core/services/relay/evm/types/types_test.go index fb394ddf38..37d5e77693 100644 --- a/core/services/relay/evm/types/types_test.go +++ b/core/services/relay/evm/types/types_test.go @@ -1,15 +1,21 @@ package types import ( + "encoding/json" "fmt" "testing" + "time" + "github.com/ethereum/go-ethereum/common" "github.com/pelletier/go-toml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/codec" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/store/models" ) // ChainID *big.Big `json:"chainID"` @@ -39,3 +45,112 @@ FeedID = "0x%x" assert.Equal(t, fromBlock, rc.FromBlock) assert.Equal(t, feedID.Hex(), rc.FeedID.Hex()) } + +func Test_ChainReaderConfig(t *testing.T) { + tests := []struct { + name string + jsonInput string + expected ChainReaderConfig + }{ + { + name: "Valid JSON", + jsonInput: ` +{ + "contracts":{ + "Contract1":{ + "contractABI":"[ { \"anonymous\": false, \"inputs\": [ { \"indexed\": true, \"internalType\": \"address\", \"name\": \"requester\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"bytes32\", \"name\": \"configDigest\", \"type\": \"bytes32\" }, { \"indexed\": false, \"internalType\": \"uint32\", \"name\": \"epoch\", \"type\": \"uint32\" }, { \"indexed\": false, \"internalType\": \"uint8\", \"name\": \"round\", \"type\": \"uint8\" } ], \"name\": \"RoundRequested\", \"type\": \"event\" }, { \"inputs\": [], \"name\": \"latestTransmissionDetails\", \"outputs\": [ { \"internalType\": \"bytes32\", \"name\": \"configDigest\", \"type\": \"bytes32\" }, { \"internalType\": \"uint32\", \"name\": \"epoch\", \"type\": \"uint32\" }, { \"internalType\": \"uint8\", \"name\": \"round\", \"type\": \"uint8\" }, { \"internalType\": \"int192\", \"name\": \"latestAnswer_\", \"type\": \"int192\" }, { \"internalType\": \"uint64\", \"name\": \"latestTimestamp_\", \"type\": \"uint64\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }]", + "contractPollingFilter":{ + "genericEventNames":[ + "event1", + "event2" + ], + "pollingFilter":{ + "topic2":[ + "0x1abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52" + ], + "topic3":[ + "0x2abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52" + ], + "topic4":[ + "0x3abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52" + ], + "retention":"1m0s", + "maxLogsKept":100, + "logsPerBlock":10 + } + }, + "configs":{ + "config1":"{\"cacheEnabled\":true,\"chainSpecificName\":\"specificName1\",\"inputModifications\":[{\"Fields\":[\"ts\"],\"Type\":\"epoch to time\"},{\"Fields\":{\"a\":\"b\"},\"Type\":\"rename\"}],\"outputModifications\":[{\"Fields\":[\"ts\"],\"Type\":\"epoch to time\"},{\"Fields\":{\"c\":\"d\"},\"Type\":\"rename\"}],\"eventDefinitions\":{\"genericTopicNames\":{\"TopicKey1\":\"TopicVal1\"},\"genericDataWordNames\":{\"DataWordKey\":1},\"inputFields\":[\"Event1\",\"Event2\"],\"pollingFilter\":{\"topic2\":[\"0x4abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"topic3\":[\"0x5abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"topic4\":[\"0x6abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52\"],\"retention\":\"1m0s\",\"maxLogsKept\":100,\"logsPerBlock\":10}},\"confidenceConfirmations\":{\"0.0\":0,\"1.0\":-1}}" + } + } + } +} +`, expected: ChainReaderConfig{ + Contracts: map[string]ChainContractReader{ + "Contract1": { + ContractABI: "[ { \"anonymous\": false, \"inputs\": [ { \"indexed\": true, \"internalType\": \"address\", \"name\": \"requester\", \"type\": \"address\" }, { \"indexed\": false, \"internalType\": \"bytes32\", \"name\": \"configDigest\", \"type\": \"bytes32\" }, { \"indexed\": false, \"internalType\": \"uint32\", \"name\": \"epoch\", \"type\": \"uint32\" }, { \"indexed\": false, \"internalType\": \"uint8\", \"name\": \"round\", \"type\": \"uint8\" } ], \"name\": \"RoundRequested\", \"type\": \"event\" }, { \"inputs\": [], \"name\": \"latestTransmissionDetails\", \"outputs\": [ { \"internalType\": \"bytes32\", \"name\": \"configDigest\", \"type\": \"bytes32\" }, { \"internalType\": \"uint32\", \"name\": \"epoch\", \"type\": \"uint32\" }, { \"internalType\": \"uint8\", \"name\": \"round\", \"type\": \"uint8\" }, { \"internalType\": \"int192\", \"name\": \"latestAnswer_\", \"type\": \"int192\" }, { \"internalType\": \"uint64\", \"name\": \"latestTimestamp_\", \"type\": \"uint64\" } ], \"stateMutability\": \"view\", \"type\": \"function\" }]", + ContractPollingFilter: ContractPollingFilter{ + GenericEventNames: []string{"event1", "event2"}, + PollingFilter: PollingFilter{ + Topic2: evmtypes.HashArray{common.HexToHash("0x1abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, + Topic3: evmtypes.HashArray{common.HexToHash("0x2abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, + Topic4: evmtypes.HashArray{common.HexToHash("0x3abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, + Retention: models.Interval(time.Minute * 1), + MaxLogsKept: 100, + LogsPerBlock: 10, + }, + }, + Configs: map[string]*ChainReaderDefinition{ + "config1": { + CacheEnabled: true, + ChainSpecificName: "specificName1", + ReadType: Method, + InputModifications: codec.ModifiersConfig{ + &codec.EpochToTimeModifierConfig{ + Fields: []string{"ts"}, + }, + &codec.RenameModifierConfig{ + Fields: map[string]string{ + "a": "b", + }, + }, + }, + OutputModifications: codec.ModifiersConfig{ + &codec.EpochToTimeModifierConfig{ + Fields: []string{"ts"}, + }, + &codec.RenameModifierConfig{ + Fields: map[string]string{ + "c": "d", + }, + }, + }, + ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": -1}, + EventDefinitions: &EventDefinitions{ + GenericTopicNames: map[string]string{"TopicKey1": "TopicVal1"}, + GenericDataWordNames: map[string]uint8{"DataWordKey": 1}, + InputFields: []string{"Event1", "Event2"}, + PollingFilter: &PollingFilter{ + Topic2: evmtypes.HashArray{common.HexToHash("0x4abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, + Topic3: evmtypes.HashArray{common.HexToHash("0x5abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, + Topic4: evmtypes.HashArray{common.HexToHash("0x6abbe4784b1fb071039bb9cb50b82978fb5d3ab98fb512c032e75786b93e2c52")}, + Retention: models.Interval(time.Minute * 1), + MaxLogsKept: 100, + LogsPerBlock: 10, + }, + }, + }, + }, + }, + }, + }, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var config ChainReaderConfig + config.Contracts = make(map[string]ChainContractReader) + require.Nil(t, json.Unmarshal([]byte(tt.jsonInput), &config)) + require.Equal(t, tt.expected, config) + }) + } +} diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index 249c3e257f..46f4f83b05 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -69,7 +69,9 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain }, }, } - cw, err := NewChainWriterService(lggr.Named("ChainWriter"), chain.Client(), chain.TxManager(), chainWriterConfig) + + chainWriterConfig.MaxGasPrice = chain.Config().EVM().GasEstimator().PriceMax() + cw, err := NewChainWriterService(lggr.Named("ChainWriter"), chain.Client(), chain.TxManager(), chain.GasEstimator(), chainWriterConfig) if err != nil { return nil, err } diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go index 4abbf16cd3..694f7e1910 100644 --- a/core/services/relay/evm/write_target_test.go +++ b/core/services/relay/evm/write_target_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" + gasmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -43,6 +44,7 @@ func TestEvmWrite(t *testing.T) { mockCall = append(mockCall, byte(0)) } evmClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(mockCall, nil).Maybe() + evmClient.On("CodeAt", mock.Anything, mock.Anything, mock.Anything).Return([]byte("test"), nil) chain.On("ID").Return(big.NewInt(11155111)) chain.On("TxManager").Return(txManager) @@ -61,8 +63,10 @@ func TestEvmWrite(t *testing.T) { c.EVM[0].Workflow.ForwarderAddress = &forwarderAddr }) evmCfg := evmtest.NewChainScopedConfig(t, cfg) + ge := gasmocks.NewEvmFeeEstimator(t) chain.On("Config").Return(evmCfg) + chain.On("GasEstimator").Return(ge) db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go new file mode 100644 index 0000000000..de3f80a5e7 --- /dev/null +++ b/core/services/relay/relay.go @@ -0,0 +1,17 @@ +package relay + +const ( + NetworkEVM = "evm" + NetworkCosmos = "cosmos" + NetworkSolana = "solana" + NetworkStarkNet = "starknet" + NetworkAptos = "aptos" +) + +var SupportedNetworks = map[string]struct{}{ + NetworkEVM: {}, + NetworkCosmos: {}, + NetworkSolana: {}, + NetworkStarkNet: {}, + NetworkAptos: {}, +} diff --git a/core/services/standardcapabilities/standard_capabilities.go b/core/services/standardcapabilities/standard_capabilities.go index 67ee8e1090..a8d007d5df 100644 --- a/core/services/standardcapabilities/standard_capabilities.go +++ b/core/services/standardcapabilities/standard_capabilities.go @@ -14,15 +14,15 @@ import ( type standardCapabilities struct { services.StateMachine - log logger.Logger - spec *job.StandardCapabilitiesSpec - pluginRegistrar plugins.RegistrarConfig - telemetryService core.TelemetryService - store core.KeyValueStore - capabilityRegistry core.CapabilitiesRegistry - errorLog core.ErrorLog - pipelineRunner core.PipelineRunnerService - relayerSet core.RelayerSet + log logger.Logger + spec *job.StandardCapabilitiesSpec + pluginRegistrar plugins.RegistrarConfig + telemetryService core.TelemetryService + store core.KeyValueStore + CapabilitiesRegistry core.CapabilitiesRegistry + errorLog core.ErrorLog + pipelineRunner core.PipelineRunnerService + relayerSet core.RelayerSet capabilitiesLoop *loop.StandardCapabilitiesService } @@ -31,20 +31,20 @@ func newStandardCapabilities(log logger.Logger, spec *job.StandardCapabilitiesSp pluginRegistrar plugins.RegistrarConfig, telemetryService core.TelemetryService, store core.KeyValueStore, - capabilityRegistry core.CapabilitiesRegistry, + CapabilitiesRegistry core.CapabilitiesRegistry, errorLog core.ErrorLog, pipelineRunner core.PipelineRunnerService, relayerSet core.RelayerSet) *standardCapabilities { return &standardCapabilities{ - log: log, - spec: spec, - pluginRegistrar: pluginRegistrar, - telemetryService: telemetryService, - store: store, - capabilityRegistry: capabilityRegistry, - errorLog: errorLog, - pipelineRunner: pipelineRunner, - relayerSet: relayerSet, + log: log, + spec: spec, + pluginRegistrar: pluginRegistrar, + telemetryService: telemetryService, + store: store, + CapabilitiesRegistry: CapabilitiesRegistry, + errorLog: errorLog, + pipelineRunner: pipelineRunner, + relayerSet: relayerSet, } } @@ -72,7 +72,7 @@ func (s *standardCapabilities) Start(ctx context.Context) error { return fmt.Errorf("error waiting for standard capabilities service to start: %v", err) } - if err = s.capabilitiesLoop.Service.Initialise(ctx, s.spec.Config, s.telemetryService, s.store, s.capabilityRegistry, s.errorLog, + if err = s.capabilitiesLoop.Service.Initialise(ctx, s.spec.Config, s.telemetryService, s.store, s.CapabilitiesRegistry, s.errorLog, s.pipelineRunner, s.relayerSet); err != nil { return fmt.Errorf("error initialising standard capabilities service: %v", err) } diff --git a/core/services/vrf/v2/listener_v2_log_processor.go b/core/services/vrf/v2/listener_v2_log_processor.go index 673f8618c0..9408768d4d 100644 --- a/core/services/vrf/v2/listener_v2_log_processor.go +++ b/core/services/vrf/v2/listener_v2_log_processor.go @@ -148,7 +148,7 @@ func (lsn *listenerV2) processPendingVRFRequests(ctx context.Context, pendingReq ) sID, ok := new(big.Int).SetString(subID, 10) if !ok { - l.Criticalw("Unable to convert %s to Int", subID) + l.Criticalf("Unable to convert %s to Int", subID) return } sub, err := lsn.coordinator.GetSubscription(&bind.CallOpts{ @@ -1049,7 +1049,8 @@ func (lsn *listenerV2) runPipelines( wg.Add(1) go func(i int, req pendingRequest) { defer wg.Done() - results[i] = lsn.simulateFulfillment(ctx, maxGasPriceWei, req, l) + ll := l.With("reqID", req.req.RequestID().String()) + results[i] = lsn.simulateFulfillment(ctx, maxGasPriceWei, req, ll) }(i, req) } wg.Wait() @@ -1103,7 +1104,6 @@ func (lsn *listenerV2) simulateFulfillment( if err != nil { // not critical, just log and continue lg.Warnw("unable to estimate funds needed for request, continuing anyway", - "reqID", req.req.RequestID(), "err", err) res.fundsNeeded = big.NewInt(0) } diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index 014b1bdb22..b937e0b580 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -2,7 +2,6 @@ package workflows import ( "context" - "encoding/hex" "fmt" "github.com/google/uuid" @@ -12,15 +11,14 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) type Delegate struct { - registry core.CapabilitiesRegistry - logger logger.Logger - peerID func() *p2ptypes.PeerID - store store.Store + registry core.CapabilitiesRegistry + logger logger.Logger + getLocalNode func(ctx context.Context) (capabilities.Node, error) + store store.Store } var _ job.Delegate = (*Delegate)(nil) @@ -38,12 +36,7 @@ func (d *Delegate) BeforeJobDeleted(spec job.Job) {} func (d *Delegate) OnDeleteJob(context.Context, job.Job) error { return nil } // ServicesForSpec satisfies the job.Delegate interface. -func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.ServiceCtx, error) { - dinfo, err := initializeDONInfo(d.logger) - if err != nil { - d.logger.Errorw("could not add initialize don info", err) - } - +func (d *Delegate) ServicesForSpec(_ context.Context, spec job.Job) ([]job.ServiceCtx, error) { cfg := Config{ Lggr: d.logger, Spec: spec.WorkflowSpec.Workflow, @@ -51,8 +44,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser WorkflowOwner: spec.WorkflowSpec.WorkflowOwner, WorkflowName: spec.WorkflowSpec.WorkflowName, Registry: d.registry, - DONInfo: dinfo, - PeerID: d.peerID, + GetLocalNode: d.getLocalNode, Store: d.store, } engine, err := NewEngine(cfg) @@ -62,49 +54,16 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return []job.ServiceCtx{engine}, nil } -func initializeDONInfo(lggr logger.Logger) (*capabilities.DON, error) { - var key [16]byte - - // TODO: fetch the key and DONInfo from the registry - keyString := "44fb5c1ee8ee48846c808a383da3aba3" - k, err := hex.DecodeString(keyString) - if err != nil { - lggr.Errorf("could not decode key %s: %w", keyString, err) - } - key = [16]byte(k) - - p2pStrings := []string{ - "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", - "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", - "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", - "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", - } - - p2pIDs := []p2ptypes.PeerID{} - for _, p := range p2pStrings { - pid := p2ptypes.PeerID{} - err := pid.UnmarshalText([]byte(p)) - if err != nil { - return nil, err - } - - p2pIDs = append(p2pIDs, pid) - } - - return &capabilities.DON{ - ID: "00010203", - Members: p2pIDs, - Config: capabilities.DONConfig{ - SharedSecret: key, - }, - }, nil -} - -func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, store store.Store, peerID func() *p2ptypes.PeerID) *Delegate { - return &Delegate{logger: logger, registry: registry, store: store, peerID: peerID} +func NewDelegate( + logger logger.Logger, + registry core.CapabilitiesRegistry, + store store.Store, + getLocalNode func(ctx context.Context) (capabilities.Node, error), +) *Delegate { + return &Delegate{logger: logger, registry: registry, store: store, getLocalNode: getLocalNode} } -func ValidatedWorkflowSpec(tomlString string) (job.Job, error) { +func ValidatedWorkflowJobSpec(tomlString string) (job.Job, error) { var jb = job.Job{ExternalJobID: uuid.New()} tree, err := toml.Load(tomlString) diff --git a/core/services/workflows/delegate_test.go b/core/services/workflows/delegate_test.go index dde01e5066..a12eac80bb 100644 --- a/core/services/workflows/delegate_test.go +++ b/core/services/workflows/delegate_test.go @@ -11,93 +11,19 @@ import ( func TestDelegate_JobSpecValidator(t *testing.T) { t.Parallel() - validName := "ten bytes!" var tt = []struct { name string workflowTomlFn func() string valid bool }{ - { - "not a hex owner", - func() string { - workflowId := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - workflowOwner := "00000000000000000000000000000000000000aZ" - return testspecs.GenerateWorkflowSpec(workflowId, workflowOwner, "1234567890", "").Toml() - }, - false, - }, - { - "missing workflow field", - func() string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" - return testspecs.GenerateWorkflowSpec(id, owner, validName, "").Toml() - }, - false, - }, - - { - "null workflow", - func() string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" - return testspecs.GenerateWorkflowSpec(id, owner, validName, "{}").Toml() - }, - false, - }, - - { - "missing name", - func() string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" - wf := ` -triggers: [] -consensus: [] -targets: [] -` - return testspecs.GenerateWorkflowSpec(id, owner, "", wf).Toml() - }, - false, - }, - - { - "minimal passing workflow", - func() string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" - wf := ` -triggers: [] -consensus: [] -targets: [] -` - return testspecs.GenerateWorkflowSpec(id, owner, validName, wf).Toml() - }, - true, - }, - - { - "name too long", - func() string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" - wf := ` -triggers: [] -consensus: [] -targets: [] -` - return testspecs.GenerateWorkflowSpec(id, owner, validName+"1", wf).Toml() - }, - false, - }, // Taken from jobs controller test, as we want to fail early without a db / slow test dependency { "valid full spec", func() string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" workflow := ` +name: "wf-name" +owner: "0x00000000000000000000000000000000000000aa" triggers: - id: "mercury-trigger@1.0.0" config: @@ -144,7 +70,7 @@ targets: params: ["$(report)"] abi: "receive(report bytes)" ` - return testspecs.GenerateWorkflowSpec(id, owner, validName, workflow).Toml() + return testspecs.GenerateWorkflowJobSpec(t, workflow).Toml() }, true, }, @@ -173,7 +99,7 @@ schemaVersion = 1 for _, tc := range tt { tc := tc t.Run(tc.name, func(t *testing.T) { - _, err := workflows.ValidatedWorkflowSpec(tc.workflowTomlFn()) + _, err := workflows.ValidatedWorkflowJobSpec(tc.workflowTomlFn()) if tc.valid { require.NoError(t, err) } else { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 47638f7143..28f37cd7c4 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -18,20 +18,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink/v2/core/capabilities/transmission" "github.com/smartcontractkit/chainlink/v2/core/logger" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) -const ( - // NOTE: max 32 bytes per ID - consider enforcing exactly 32 bytes? - mockedTriggerID = "cccccccccc0000000000000000000000" -) - -type donInfo struct { - *capabilities.DON - PeerID func() *p2ptypes.PeerID -} - type stepRequest struct { stepRef string state store.WorkflowExecution @@ -43,7 +32,8 @@ type Engine struct { logger logger.Logger registry core.CapabilitiesRegistry workflow *workflow - donInfo donInfo + getLocalNode func(ctx context.Context) (capabilities.Node, error) + localNode capabilities.Node executionStates store.Store pendingStepRequests chan stepRequest triggerEvents chan capabilities.CapabilityResponse @@ -141,18 +131,20 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { return fmt.Errorf("failed to get capability with ref %s: %s", step.ID, err) } - // Special treatment for local targets - wrap into a transmission capability - target, isTarget := cp.(capabilities.TargetCapability) - if isTarget { - capInfo, err2 := target.Info(ctx) - if err2 != nil { - return fmt.Errorf("failed to get info of target capability: %w", err2) - } + info, err := cp.Info(ctx) + if err != nil { + return fmt.Errorf("failed to get info of capability with id %s: %w", step.ID, err) + } - // If the DON is nil this is a local target - if capInfo.DON == nil { - cp = transmission.NewLocalTargetCapability(e.logger, *e.donInfo.PeerID(), *e.donInfo.DON, target) - } + // Special treatment for local targets - wrap into a transmission capability + // If the DON is nil, this is a local target. + if info.CapabilityType == capabilities.CapabilityTypeTarget && info.DON == nil { + e.logger.Debugf("wrapping capability %s in local transmission protocol", info.ID) + cp = transmission.NewLocalTargetCapability( + e.logger, + e.localNode, + cp.(capabilities.TargetCapability), + ) } // We configure actions, consensus and targets here, and @@ -188,16 +180,25 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { // init does the following: // -// 1. Resolves the underlying capability for each trigger -// 2. Registers each step's capability to this workflow -// 3. Registers for trigger events now that all capabilities are resolved +// 1. Resolves the LocalDON information +// 2. Resolves the underlying capability for each trigger +// 3. Registers each step's capability to this workflow +// 4. Registers for trigger events now that all capabilities are resolved // -// Steps 1 and 2 are retried every 5 seconds until successful. +// Steps 1-3 are retried every 5 seconds until successful. func (e *Engine) init(ctx context.Context) { defer e.wg.Done() retryErr := retryable(ctx, e.logger, e.retryMs, e.maxRetries, func() error { - err := e.resolveWorkflowCapabilities(ctx) + // first wait for localDON to return a non-error response; this depends + // on the underlying peerWrapper returning the PeerID. + node, err := e.getLocalNode(ctx) + if err != nil { + return fmt.Errorf("failed to get donInfo: %w", err) + } + e.localNode = node + + err = e.resolveWorkflowCapabilities(ctx) if err != nil { return fmt.Errorf("failed to resolve workflow: %s", err) } @@ -213,12 +214,12 @@ func (e *Engine) init(ctx context.Context) { e.logger.Debug("capabilities resolved, resuming in-progress workflows") err := e.resumeInProgressExecutions(ctx) if err != nil { - e.logger.Errorf("failed to resume workflows: %w", err) + e.logger.Errorf("failed to resume workflows: %v", err) } e.logger.Debug("registering triggers") - for _, t := range e.workflow.triggers { - err := e.registerTrigger(ctx, t) + for idx, t := range e.workflow.triggers { + err := e.registerTrigger(ctx, t, idx) if err != nil { e.logger.Errorf("failed to register trigger: %s", err) } @@ -277,11 +278,15 @@ func (e *Engine) resumeInProgressExecutions(ctx context.Context) error { return nil } +func generateTriggerId(workflowID string, triggerIdx int) string { + return fmt.Sprintf("wf_%s_trigger_%d", workflowID, triggerIdx) +} + // registerTrigger is used during the initialization phase to bind a trigger to this workflow -func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) error { +func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, triggerIdx int) error { triggerInputs, err := values.NewMap( map[string]any{ - "triggerId": mockedTriggerID, + "triggerId": generateTriggerId(e.workflow.id, triggerIdx), }, ) if err != nil { @@ -298,7 +303,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) erro triggerRegRequest := capabilities.CapabilityRequest{ Metadata: capabilities.RequestMetadata{ WorkflowID: e.workflow.id, - WorkflowDonID: e.donInfo.ID, + WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowName: e.workflow.name, WorkflowOwner: e.workflow.owner, }, @@ -348,26 +353,26 @@ func (e *Engine) loop(ctx context.Context) { } if resp.Err != nil { - e.logger.Errorf("trigger event was an error; not executing", resp.Err) + e.logger.Errorf("trigger event was an error %v; not executing", resp.Err) continue } te := &capabilities.TriggerEvent{} err := resp.Value.UnwrapTo(te) if err != nil { - e.logger.Errorf("could not unwrap trigger event", resp.Err) + e.logger.Errorf("could not unwrap trigger event; error %v", resp.Err) continue } executionID, err := generateExecutionID(e.workflow.id, te.ID) if err != nil { - e.logger.Errorf("could not generate execution ID", resp.Err) + e.logger.Errorf("could not generate execution ID; error %v", resp.Err) continue } err = e.startExecution(ctx, executionID, resp.Value) if err != nil { - e.logger.Errorf("failed to start execution: %w", err) + e.logger.Errorf("failed to start execution: %v", err) } case pendingStepRequest := <-e.pendingStepRequests: // Wait for a new worker to be available before dispatching a new one. @@ -583,7 +588,7 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { inputs, outputs, err := e.executeStep(ctx, l, msg) var stepStatus string switch { - case errors.Is(err, capabilities.ErrStopExecution): + case errors.Is(capabilities.ErrStopExecution, err): l.Infow("step executed successfully with a termination") stepStatus = store.StatusCompletedEarlyExit case err != nil: @@ -607,7 +612,7 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // like this one will get picked up again and will be reprocessed. select { case <-ctx.Done(): - l.Errorf("context canceled before step update could be issued", err) + l.Errorf("context canceled before step update could be issued; error %v", err) case e.stepUpdateCh <- *stepState: } } @@ -637,7 +642,7 @@ func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepReque WorkflowExecutionID: msg.state.ExecutionID, WorkflowOwner: e.workflow.owner, WorkflowName: e.workflow.name, - WorkflowDonID: e.donInfo.ID, + WorkflowDonID: e.localNode.WorkflowDON.ID, }, } @@ -649,10 +654,10 @@ func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepReque return inputs, output, err } -func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability) error { +func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, triggerIdx int) error { triggerInputs, err := values.NewMap( map[string]any{ - "triggerId": mockedTriggerID, + "triggerId": generateTriggerId(e.workflow.id, triggerIdx), }, ) if err != nil { @@ -661,7 +666,7 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability) er deregRequest := capabilities.CapabilityRequest{ Metadata: capabilities.RequestMetadata{ WorkflowID: e.workflow.id, - WorkflowDonID: e.donInfo.ID, + WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowName: e.workflow.name, WorkflowOwner: e.workflow.owner, }, @@ -687,8 +692,8 @@ func (e *Engine) Close() error { // any triggers to ensure no new executions are triggered, // then we'll close down any background goroutines, // and finally, we'll deregister any workflow steps. - for _, t := range e.workflow.triggers { - err := e.deregisterTrigger(ctx, t) + for idx, t := range e.workflow.triggers { + err := e.deregisterTrigger(ctx, t, idx) if err != nil { return err } @@ -742,8 +747,7 @@ type Config struct { QueueSize int NewWorkerTimeout time.Duration MaxExecutionDuration time.Duration - DONInfo *capabilities.DON - PeerID func() *p2ptypes.PeerID + GetLocalNode func(ctx context.Context) (capabilities.Node, error) Store store.Store // For testing purposes only @@ -762,6 +766,10 @@ const ( ) func NewEngine(cfg Config) (engine *Engine, err error) { + if cfg.Store == nil { + return nil, errors.New("must provide store") + } + if cfg.MaxWorkerLimit == 0 { cfg.MaxWorkerLimit = defaultWorkerLimit } @@ -778,8 +786,10 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.MaxExecutionDuration = defaultMaxExecutionDuration } - if cfg.Store == nil { - cfg.Store = store.NewInMemoryStore() + if cfg.GetLocalNode == nil { + cfg.GetLocalNode = func(ctx context.Context) (capabilities.Node, error) { + return capabilities.Node{}, nil + } } if cfg.retryMs == 0 { @@ -822,13 +832,10 @@ func NewEngine(cfg Config) (engine *Engine, err error) { } engine = &Engine{ - logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), - registry: cfg.Registry, - workflow: workflow, - donInfo: donInfo{ - DON: cfg.DONInfo, - PeerID: cfg.PeerID, - }, + logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), + registry: cfg.Registry, + workflow: workflow, + getLocalNode: cfg.GetLocalNode, executionStates: cfg.Store, pendingStepRequests: make(chan stepRequest, cfg.QueueSize), newWorkerCh: newWorkerCh, diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index ddb08c2431..09af6d6358 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -3,6 +3,7 @@ package workflows import ( "context" "errors" + "fmt" "testing" "time" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink-common/pkg/workflows" coreCap "github.com/smartcontractkit/chainlink/v2/core/capabilities" @@ -72,6 +74,7 @@ targets: type testHooks struct { initFailed chan struct{} + initSuccessful chan struct{} executionFinished chan string } @@ -79,33 +82,42 @@ type testHooks struct { func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...func(c *Config)) (*Engine, *testHooks) { peerID := p2ptypes.PeerID{} initFailed := make(chan struct{}) + initSuccessful := make(chan struct{}) executionFinished := make(chan string, 100) + clock := clockwork.NewFakeClock() cfg := Config{ Lggr: logger.TestLogger(t), Registry: reg, Spec: spec, - DONInfo: &capabilities.DON{ - ID: "00010203", + GetLocalNode: func(ctx context.Context) (capabilities.Node, error) { + return capabilities.Node{ + WorkflowDON: capabilities.DON{ + ID: "00010203", + }, + PeerID: &peerID, + }, nil }, - PeerID: func() *p2ptypes.PeerID { return &peerID }, maxRetries: 1, retryMs: 100, afterInit: func(success bool) { - if !success { + if success { + close(initSuccessful) + } else { close(initFailed) } }, onExecutionFinished: func(weid string) { executionFinished <- weid }, - clock: clockwork.NewFakeClock(), + clock: clock, + Store: store.NewDBStore(pgtest.NewSqlxDB(t), clock), } for _, o := range opts { o(&cfg) } eng, err := NewEngine(cfg) require.NoError(t, err) - return eng, &testHooks{initFailed: initFailed, executionFinished: executionFinished} + return eng, &testHooks{initSuccessful: initSuccessful, initFailed: initFailed, executionFinished: executionFinished} } // getExecutionId returns the execution id of the workflow that is @@ -181,69 +193,49 @@ func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capab } func TestEngineWithHardcodedWorkflow(t *testing.T) { - t.Parallel() + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()) + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) - testCases := []struct { - name string - store store.Store - }{ - { - name: "db-engine", - store: store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()), - }, - { - name: "in-memory-engine", - store: store.NewInMemoryStore(), + trigger, cr := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + target1 := mockTarget() + require.NoError(t, reg.Add(ctx, target1)) + + target2 := newMockCapability( + capabilities.MustNewCapabilityInfo( + "write_ethereum-testnet-sepolia@1.0.0", + capabilities.CapabilityTypeTarget, + "a write capability targeting ethereum sepolia testnet", + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + m := req.Inputs.Underlying["report"].(*values.Map) + return capabilities.CapabilityResponse{ + Value: m, + }, nil }, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - ctx := testutils.Context(t) - reg := coreCap.NewRegistry(logger.TestLogger(t)) - - trigger, cr := mockTrigger(t) - - require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - target1 := mockTarget() - require.NoError(t, reg.Add(ctx, target1)) - - target2 := newMockCapability( - capabilities.MustNewCapabilityInfo( - "write_ethereum-testnet-sepolia@1.0.0", - capabilities.CapabilityTypeTarget, - "a write capability targeting ethereum sepolia testnet", - ), - func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { - m := req.Inputs.Underlying["report"].(*values.Map) - return capabilities.CapabilityResponse{ - Value: m, - }, nil - }, - ) - require.NoError(t, reg.Add(ctx, target2)) + ) + require.NoError(t, reg.Add(ctx, target2)) - eng, testHooks := newTestEngine( - t, - reg, - hardcodedWorkflow, - func(c *Config) { c.Store = tc.store }, - ) + eng, testHooks := newTestEngine( + t, + reg, + hardcodedWorkflow, + func(c *Config) { c.Store = dbstore }, + ) - err := eng.Start(ctx) - require.NoError(t, err) - defer eng.Close() + servicetest.Run(t, eng) - eid := getExecutionId(t, eng, testHooks) - assert.Equal(t, cr, <-target1.response) - assert.Equal(t, cr, <-target2.response) + eid := getExecutionId(t, eng, testHooks) + assert.Equal(t, cr, <-target1.response) + assert.Equal(t, cr, <-target2.response) - state, err := eng.executionStates.Get(ctx, eid) - require.NoError(t, err) + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) - assert.Equal(t, state.Status, store.StatusCompleted) - }) - } + assert.Equal(t, state.Status, store.StatusCompleted) } const ( @@ -345,7 +337,8 @@ func mockConsensusWithEarlyTermination() *mockCapability { ), func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { return capabilities.CapabilityResponse{ - Err: capabilities.ErrStopExecution, + // copy error object to make sure message comparison works as expected + Err: errors.New(capabilities.ErrStopExecution.Error()), }, nil }, ) @@ -405,9 +398,7 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { eng, hooks := newTestEngine(t, reg, simpleWorkflow) - err := eng.Start(ctx) - require.NoError(t, err) - defer eng.Close() + servicetest.Run(t, eng) eid := getExecutionId(t, eng, hooks) state, err := eng.executionStates.Get(ctx, eid) @@ -430,10 +421,7 @@ func TestEngine_GracefulEarlyTermination(t *testing.T) { require.NoError(t, reg.Add(ctx, mockTarget())) eng, hooks := newTestEngine(t, reg, simpleWorkflow) - - err := eng.Start(ctx) - require.NoError(t, err) - defer eng.Close() + servicetest.Run(t, eng) eid := getExecutionId(t, eng, hooks) state, err := eng.executionStates.Get(ctx, eid) @@ -526,9 +514,7 @@ func TestEngine_MultiStepDependencies(t *testing.T) { require.NoError(t, reg.Add(ctx, action)) eng, hooks := newTestEngine(t, reg, multiStepWorkflow) - err := eng.Start(ctx) - require.NoError(t, err) - defer eng.Close() + servicetest.Run(t, eng) eid := getExecutionId(t, eng, hooks) state, err := eng.executionStates.Get(ctx, eid) @@ -599,8 +585,7 @@ func TestEngine_ResumesPendingExecutions(t *testing.T) { multiStepWorkflow, func(c *Config) { c.Store = dbstore }, ) - err = eng.Start(ctx) - require.NoError(t, err) + servicetest.Run(t, eng) eid := getExecutionId(t, eng, hooks) gotEx, err := dbstore.Get(ctx, eid) @@ -658,11 +643,151 @@ func TestEngine_TimesOutOldExecutions(t *testing.T) { }, ) clock.Advance(15 * time.Minute) - err = eng.Start(ctx) - require.NoError(t, err) + servicetest.Run(t, eng) _ = getExecutionId(t, eng, hooks) gotEx, err := dbstore.Get(ctx, "") require.NoError(t, err) assert.Equal(t, store.StatusTimeout, gotEx.Status) } + +const ( + delayedWorkflow = ` +triggers: + - id: "mercury-trigger@1.0.0" + config: + feedlist: + - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD + - "0x2222222222222222222200000000000000000000000000000000000000000000" # LINKUSD + - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD + +consensus: + - id: "offchain_reporting@1.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + aggregation_method: "data_feeds_2_0" + aggregation_config: + "0x1111111111111111111100000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + "0x2222222222222222222200000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + "0x3333333333333333333300000000000000000000000000000000000000000000": + deviation: "0.001" + heartbeat: "30m" + encoder: "EVM" + encoder_config: + abi: "mercury_reports bytes[]" + +targets: + - id: "write_polygon-testnet-mumbai@1.0.0" + inputs: + report: "$(evm_median.outputs.report)" + config: + address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" + params: ["$(report)"] + abi: "receive(report bytes)" + deltaStage: 2s + schedule: allAtOnce +` +) + +func TestEngine_WrapsTargets(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, _ := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + clock := clockwork.NewFakeClock() + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + + eng, hooks := newTestEngine( + t, + reg, + delayedWorkflow, + func(c *Config) { + c.Store = dbstore + c.clock = clock + }, + ) + servicetest.Run(t, eng) + + <-hooks.initSuccessful + + err := eng.workflow.walkDo(workflows.KeywordTrigger, func(s *step) error { + if s.Ref == workflows.KeywordTrigger { + return nil + } + + info, err2 := s.capability.Info(ctx) + require.NoError(t, err2) + + if info.CapabilityType == capabilities.CapabilityTypeTarget { + assert.Equal(t, "*transmission.LocalTargetCapability", fmt.Sprintf("%T", s.capability)) + } else { + assert.NotEqual(t, "*transmission.LocalTargetCapability", fmt.Sprintf("%T", s.capability)) + } + + return nil + }) + require.NoError(t, err) +} + +func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, _ := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + clock := clockwork.NewFakeClock() + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + + var peerID p2ptypes.PeerID + node := capabilities.Node{ + PeerID: &peerID, + WorkflowDON: capabilities.DON{ + ID: "1", + }, + } + retryCount := 0 + eng, hooks := newTestEngine( + t, + reg, + delayedWorkflow, + func(c *Config) { + c.Store = dbstore + c.clock = clock + c.maxRetries = 2 + c.retryMs = 0 + c.GetLocalNode = func(ctx context.Context) (capabilities.Node, error) { + n := capabilities.Node{} + err := errors.New("peer not initialized") + if retryCount > 0 { + n = node + err = nil + } + retryCount++ + return n, err + } + }, + ) + servicetest.Run(t, eng) + + <-hooks.initSuccessful + + assert.Equal(t, node, eng.localNode) +} diff --git a/core/services/workflows/store/models.go b/core/services/workflows/store/models.go index 8b4632b1f8..275ca85b4f 100644 --- a/core/services/workflows/store/models.go +++ b/core/services/workflows/store/models.go @@ -6,6 +6,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/values" ) +// Note: any update to the enum below should be reflected in +// ValidStatuses and the database enum `workflow_status`. const ( StatusStarted = "started" StatusErrored = "errored" @@ -14,6 +16,14 @@ const ( StatusCompletedEarlyExit = "completed_early_exit" ) +var ValidStatuses = map[string]bool{ + StatusStarted: true, + StatusErrored: true, + StatusTimeout: true, + StatusCompleted: true, + StatusCompletedEarlyExit: true, +} + type StepOutput struct { Err error Value values.Value diff --git a/core/services/workflows/store/store.go b/core/services/workflows/store/store.go index e77050617a..72045ea062 100644 --- a/core/services/workflows/store/store.go +++ b/core/services/workflows/store/store.go @@ -12,5 +12,4 @@ type Store interface { GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) } -var _ Store = (*InMemoryStore)(nil) var _ Store = (*DBStore)(nil) diff --git a/core/services/workflows/store/store_db_test.go b/core/services/workflows/store/store_db_test.go index e30eda1bfc..7ae139b943 100644 --- a/core/services/workflows/store/store_db_test.go +++ b/core/services/workflows/store/store_db_test.go @@ -34,16 +34,16 @@ func Test_StoreDB(t *testing.T) { "step1": { ExecutionID: id, Ref: "step1", - Status: "completed", + Status: StatusCompleted, }, "step2": { ExecutionID: id, Ref: "step2", - Status: "started", + Status: StatusStarted, }, }, ExecutionID: id, - Status: "started", + Status: StatusStarted, } err := store.Add(tests.Context(t), &es) @@ -67,16 +67,16 @@ func Test_StoreDB_DuplicateEntry(t *testing.T) { "step1": { ExecutionID: id, Ref: "step1", - Status: "completed", + Status: StatusCompleted, }, "step2": { ExecutionID: id, Ref: "step2", - Status: "started", + Status: StatusStarted, }, }, ExecutionID: id, - Status: "started", + Status: StatusStarted, } err := store.Add(tests.Context(t), &es) @@ -96,23 +96,23 @@ func Test_StoreDB_UpdateStatus(t *testing.T) { "step1": { ExecutionID: id, Ref: "step1", - Status: "completed", + Status: StatusCompleted, }, "step2": { ExecutionID: id, Ref: "step2", - Status: "started", + Status: StatusStarted, }, }, ExecutionID: id, - Status: "started", + Status: StatusStarted, } err := store.Add(tests.Context(t), &es) require.NoError(t, err) - completedStatus := "completed" - err = store.UpdateStatus(tests.Context(t), es.ExecutionID, "completed") + completedStatus := StatusCompleted + err = store.UpdateStatus(tests.Context(t), es.ExecutionID, StatusCompleted) require.NoError(t, err) gotEs, err := store.Get(tests.Context(t), es.ExecutionID) @@ -129,12 +129,12 @@ func Test_StoreDB_UpdateStep(t *testing.T) { stepOne := &WorkflowExecutionStep{ ExecutionID: id, Ref: "step1", - Status: "completed", + Status: StatusCompleted, } stepTwo := &WorkflowExecutionStep{ ExecutionID: id, Ref: "step2", - Status: "started", + Status: StatusStarted, } es := WorkflowExecution{ Steps: map[string]*WorkflowExecutionStep{ @@ -142,13 +142,13 @@ func Test_StoreDB_UpdateStep(t *testing.T) { "step2": stepTwo, }, ExecutionID: id, - Status: "started", + Status: StatusStarted, } err := store.Add(tests.Context(t), &es) require.NoError(t, err) - stepOne.Status = "completed" + stepOne.Status = StatusCompleted nm, err := values.NewMap(map[string]any{"hello": "world"}) require.NoError(t, err) @@ -169,6 +169,70 @@ func Test_StoreDB_UpdateStep(t *testing.T) { assert.Equal(t, stepTwo, gotStep) } +func Test_StoreDB_WorkflowStatus(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + for s := range ValidStatuses { + id := randomID() + stepOne := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step1", + Status: StatusCompleted, + } + stepTwo := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step2", + Status: StatusStarted, + } + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": stepOne, + "step2": stepTwo, + }, + ExecutionID: id, + Status: s, + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + } +} + +func Test_StoreDB_WorkflowStepStatus(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + stepOne := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step1", + Status: StatusCompleted, + } + stepTwo := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step2", + Status: StatusStarted, + } + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": stepOne, + "step2": stepTwo, + }, + ExecutionID: id, + Status: StatusStarted, + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + for s := range ValidStatuses { + stepOne.Status = s + _, err := store.UpsertStep(tests.Context(t), stepOne) + require.NoError(t, err) + } +} + func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { db := pgtest.NewSqlxDB(t) store := &DBStore{db: db, clock: clockwork.NewFakeClock()} @@ -177,12 +241,12 @@ func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { stepOne := &WorkflowExecutionStep{ ExecutionID: id, Ref: "step1", - Status: "completed", + Status: StatusCompleted, } stepTwo := &WorkflowExecutionStep{ ExecutionID: id, Ref: "step2", - Status: "started", + Status: StatusStarted, } es := WorkflowExecution{ Steps: map[string]*WorkflowExecutionStep{ @@ -190,7 +254,7 @@ func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { "step2": stepTwo, }, ExecutionID: id, - Status: "started", + Status: StatusStarted, } err := store.Add(tests.Context(t), &es) @@ -199,7 +263,7 @@ func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { id = randomID() esTwo := WorkflowExecution{ ExecutionID: id, - Status: "completed", + Status: StatusCompleted, Steps: map[string]*WorkflowExecutionStep{}, } err = store.Add(tests.Context(t), &esTwo) diff --git a/core/services/workflows/store/store_memory.go b/core/services/workflows/store/store_memory.go deleted file mode 100644 index 7c8226c5d9..0000000000 --- a/core/services/workflows/store/store_memory.go +++ /dev/null @@ -1,86 +0,0 @@ -package store - -import ( - "context" - "fmt" - "sync" -) - -// `InMemoryStore` is a temporary in-memory -// equivalent of the database table that should persist -// workflow progress. -type InMemoryStore struct { - idToState map[string]*WorkflowExecution - mu sync.RWMutex -} - -func NewInMemoryStore() *InMemoryStore { - return &InMemoryStore{idToState: map[string]*WorkflowExecution{}} -} - -// Add adds a new execution state under the given executionID -func (s *InMemoryStore) Add(ctx context.Context, state *WorkflowExecution) error { - s.mu.Lock() - defer s.mu.Unlock() - _, ok := s.idToState[state.ExecutionID] - if ok { - return fmt.Errorf("execution ID %s already exists in store", state.ExecutionID) - } - - s.idToState[state.ExecutionID] = state - return nil -} - -// UpsertStep updates a step for the given executionID -func (s *InMemoryStore) UpsertStep(ctx context.Context, step *WorkflowExecutionStep) (WorkflowExecution, error) { - s.mu.Lock() - defer s.mu.Unlock() - state, ok := s.idToState[step.ExecutionID] - if !ok { - return WorkflowExecution{}, fmt.Errorf("could not find execution %s", step.ExecutionID) - } - - state.Steps[step.Ref] = step - return *state, nil -} - -// UpdateStatus updates the status for the given executionID -func (s *InMemoryStore) UpdateStatus(ctx context.Context, executionID string, status string) error { - s.mu.Lock() - defer s.mu.Unlock() - state, ok := s.idToState[executionID] - if !ok { - return fmt.Errorf("could not find execution %s", executionID) - } - - state.Status = status - return nil -} - -// Get gets the state for the given executionID -func (s *InMemoryStore) Get(ctx context.Context, executionID string) (WorkflowExecution, error) { - s.mu.RLock() - defer s.mu.RUnlock() - state, ok := s.idToState[executionID] - if !ok { - return WorkflowExecution{}, fmt.Errorf("could not find execution %s", executionID) - } - - return *state, nil -} - -// GetUnfinished gets the states for execution that are in a started state -// Offset and limit are ignored for the in-memory store. -func (s *InMemoryStore) GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) { - s.mu.RLock() - defer s.mu.RUnlock() - - states := []WorkflowExecution{} - for _, s := range s.idToState { - if s.Status == StatusStarted { - states = append(states, *s) - } - } - - return states, nil -} diff --git a/core/sessions/ldapauth/ldap.go b/core/sessions/ldapauth/ldap.go index efbedcd8d1..7e84339e28 100644 --- a/core/sessions/ldapauth/ldap.go +++ b/core/sessions/ldapauth/ldap.go @@ -142,7 +142,7 @@ func (l *ldapAuthenticator) FindUser(ctx context.Context, email string) (session conn, err := l.ldapClient.CreateEphemeralConnection() if err != nil { - l.lggr.Errorf("error in LDAP dial: ", err) + l.lggr.Errorf("error in LDAP dial: %v", err) return sessions.User{}, errors.New("unable to establish connection to LDAP server with provided URL and credentials") } defer conn.Close() @@ -242,7 +242,7 @@ func (l *ldapAuthenticator) ListUsers(ctx context.Context) ([]sessions.User, err conn, err := l.ldapClient.CreateEphemeralConnection() if err != nil { - l.lggr.Errorf("error in LDAP dial: ", err) + l.lggr.Errorf("error in LDAP dial: %v", err) return users, errors.New("unable to establish connection to LDAP server with provided URL and credentials") } defer conn.Close() @@ -250,25 +250,25 @@ func (l *ldapAuthenticator) ListUsers(ctx context.Context) ([]sessions.User, err // Query for list of uniqueMember IDs present in Admin group adminUsers, err := l.ldapGroupMembersListToUser(conn, l.config.AdminUserGroupCN(), sessions.UserRoleAdmin) if err != nil { - l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err) + l.lggr.Errorf("error in ldapGroupMembersListToUser: %v", err) return users, errors.New("unable to list group users") } // Query for list of uniqueMember IDs present in Edit group editUsers, err := l.ldapGroupMembersListToUser(conn, l.config.EditUserGroupCN(), sessions.UserRoleEdit) if err != nil { - l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err) + l.lggr.Error("error in ldapGroupMembersListToUser: ", err) return users, errors.New("unable to list group users") } // Query for list of uniqueMember IDs present in Run group runUsers, err := l.ldapGroupMembersListToUser(conn, l.config.RunUserGroupCN(), sessions.UserRoleRun) if err != nil { - l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err) + l.lggr.Error("error in ldapGroupMembersListToUser: ", err) return users, errors.New("unable to list group users") } // Query for list of uniqueMember IDs present in Read group readUsers, err := l.ldapGroupMembersListToUser(conn, l.config.ReadUserGroupCN(), sessions.UserRoleView) if err != nil { - l.lggr.Errorf("error in ldapGroupMembersListToUser: ", err) + l.lggr.Error("error in ldapGroupMembersListToUser: ", err) return users, errors.New("unable to list group users") } @@ -300,7 +300,7 @@ func (l *ldapAuthenticator) ListUsers(ctx context.Context) ([]sessions.User, err } activeUsers, err := l.validateUsersActive(emails) if err != nil { - l.lggr.Errorf("error validating supplied user list: ", err) + l.lggr.Error("error validating supplied user list: ", err) return users, errors.New("error validating supplied user list") } @@ -316,7 +316,7 @@ func (l *ldapAuthenticator) ListUsers(ctx context.Context) ([]sessions.User, err var localAdminUsers []sessions.User sql := "SELECT * FROM users ORDER BY email ASC;" if err := l.ds.SelectContext(ctx, &localAdminUsers, sql); err != nil { - l.lggr.Errorf("error extending upstream LDAP users with local admin users in users table: ", err) + l.lggr.Error("error extending upstream LDAP users with local admin users in users table: ", err) } else { returnUsers = append(returnUsers, localAdminUsers...) } @@ -652,7 +652,7 @@ func (l *ldapAuthenticator) validateUsersActive(emails []string) ([]bool, error) conn, err := l.ldapClient.CreateEphemeralConnection() if err != nil { - l.lggr.Errorf("error in LDAP dial: ", err) + l.lggr.Error("error in LDAP dial: ", err) return validUsers, errors.New("unable to establish connection to LDAP server with provided URL and credentials") } defer conn.Close() diff --git a/core/sessions/ldapauth/sync.go b/core/sessions/ldapauth/sync.go index a6e0366e21..5eeaf05152 100644 --- a/core/sessions/ldapauth/sync.go +++ b/core/sessions/ldapauth/sync.go @@ -94,38 +94,38 @@ func (ldSync *LDAPServerStateSyncer) Work() { conn, err := ldSync.ldapClient.CreateEphemeralConnection() if err != nil { - ldSync.lggr.Errorf("Failed to Dial LDAP Server", err) + ldSync.lggr.Error("Failed to Dial LDAP Server: ", err) return } // Root level root user auth with credentials provided from config bindStr := ldSync.config.BaseUserAttr() + "=" + ldSync.config.ReadOnlyUserLogin() + "," + ldSync.config.BaseDN() if err = conn.Bind(bindStr, ldSync.config.ReadOnlyUserPass()); err != nil { - ldSync.lggr.Errorf("Unable to login as initial root LDAP user", err) + ldSync.lggr.Error("Unable to login as initial root LDAP user: ", err) } defer conn.Close() // Query for list of uniqueMember IDs present in Admin group adminUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.AdminUserGroupCN(), sessions.UserRoleAdmin) if err != nil { - ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err) + ldSync.lggr.Error("Error in ldapGroupMembersListToUser: ", err) return } // Query for list of uniqueMember IDs present in Edit group editUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.EditUserGroupCN(), sessions.UserRoleEdit) if err != nil { - ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err) + ldSync.lggr.Error("Error in ldapGroupMembersListToUser: ", err) return } // Query for list of uniqueMember IDs present in Edit group runUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.RunUserGroupCN(), sessions.UserRoleRun) if err != nil { - ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err) + ldSync.lggr.Error("Error in ldapGroupMembersListToUser: ", err) return } // Query for list of uniqueMember IDs present in Edit group readUsers, err := ldSync.ldapGroupMembersListToUser(conn, ldSync.config.ReadUserGroupCN(), sessions.UserRoleView) if err != nil { - ldSync.lggr.Errorf("Error in ldapGroupMembersListToUser: ", err) + ldSync.lggr.Error("Error in ldapGroupMembersListToUser: ", err) return } @@ -149,7 +149,7 @@ func (ldSync *LDAPServerStateSyncer) Work() { // list group members that are no longer marked as active usersActiveFlags, err := ldSync.validateUsersActive(dedupedEmails, conn) if err != nil { - ldSync.lggr.Errorf("Error validating supplied user list: ", err) + ldSync.lggr.Error("Error validating supplied user list: ", err) } // Remove users in the upstreamUserStateMap source of truth who are part of groups but marked as deactivated/no-active for i, active := range usersActiveFlags { @@ -252,7 +252,7 @@ func (ldSync *LDAPServerStateSyncer) Work() { return nil }) if err != nil { - ldSync.lggr.Errorf("Error syncing local database state: ", err) + ldSync.lggr.Error("Error syncing local database state: ", err) } ldSync.lggr.Info("Upstream LDAP sync complete") } diff --git a/core/sessions/localauth/orm.go b/core/sessions/localauth/orm.go index de0688b9ff..1f160a40fb 100644 --- a/core/sessions/localauth/orm.go +++ b/core/sessions/localauth/orm.go @@ -274,13 +274,13 @@ func (o *orm) UpdateRole(ctx context.Context, email, newRole string) (sessions.U _, err = tx.ExecContext(ctx, "DELETE FROM sessions WHERE email = lower($1)", email) if err != nil { - o.lggr.Errorf("Failed to purge user sessions for UpdateRole", "err", err) + o.lggr.Errorw("Failed to purge user sessions for UpdateRole", "err", err) return pkgerrors.New("error updating API user") } sql := "UPDATE users SET role = $1, updated_at = now() WHERE lower(email) = lower($2) RETURNING *" if err := tx.GetContext(ctx, &userToEdit, sql, userToEdit.Role, email); err != nil { - o.lggr.Errorf("Error updating API user", "err", err) + o.lggr.Errorw("Error updating API user", "err", err) return pkgerrors.New("error updating API user") } diff --git a/core/store/migrate/migrations/0244_update_workflow_status_enum.sql b/core/store/migrate/migrations/0244_update_workflow_status_enum.sql new file mode 100644 index 0000000000..9cb759b116 --- /dev/null +++ b/core/store/migrate/migrations/0244_update_workflow_status_enum.sql @@ -0,0 +1,6 @@ +-- +goose Up +ALTER TYPE workflow_status ADD VALUE 'completed_early_exit'; + +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/core/store/migrate/migrations/0245_mv_emv_txm_types.sql b/core/store/migrate/migrations/0245_mv_emv_txm_types.sql new file mode 100644 index 0000000000..c21e976da4 --- /dev/null +++ b/core/store/migrate/migrations/0245_mv_emv_txm_types.sql @@ -0,0 +1,13 @@ +-- +goose Up +ALTER TYPE eth_txes_state RENAME TO txes_state; +ALTER TYPE txes_state SET SCHEMA "evm"; + +ALTER TYPE eth_tx_attempts_state RENAME TO tx_attempts_state; +ALTER TYPE tx_attempts_state SET SCHEMA "evm"; +-- +goose Down +ALTER TYPE evm.txes_state SET SCHEMA "public"; +ALTER TYPE txes_state RENAME TO eth_txes_state; + +ALTER TYPE evm.tx_attempts_state SET SCHEMA "public"; +ALTER TYPE tx_attempts_state RENAME TO eth_tx_attempts_state; + diff --git a/core/testdata/testspecs/v2_specs.go b/core/testdata/testspecs/v2_specs.go index fb0e019d93..949515b335 100644 --- a/core/testdata/testspecs/v2_specs.go +++ b/core/testdata/testspecs/v2_specs.go @@ -4,14 +4,19 @@ import ( "fmt" "strconv" "strings" + "testing" "time" "github.com/google/uuid" + "github.com/test-go/testify/require" + pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows" ) var ( @@ -864,26 +869,72 @@ ds -> ds_parse -> ds_multiply; return StreamSpec{StreamSpecParams: params, toml: toml} } -type WorkflowSpec struct { +// WorkflowJobSpec is a test helper that wraps both the TOML and job.Job representation of a workflow job spec +type WorkflowJobSpec struct { toml string + j job.Job } -func (w WorkflowSpec) Toml() string { +func (w WorkflowJobSpec) Toml() string { return w.toml } -func GenerateWorkflowSpec(id, owner, name, spec string) WorkflowSpec { +func (w WorkflowJobSpec) Job() job.Job { + return w.j +} + +// GenerateWorkflowJobSpec creates a WorkflowJobSpec from the given workflow yaml spec string +func GenerateWorkflowJobSpec(t *testing.T, spec string) WorkflowJobSpec { + t.Helper() + s, err := pkgworkflows.ParseWorkflowSpecYaml(spec) + require.NoError(t, err, "failed to parse YAML workflow spec %s", spec) + id := s.CID template := ` type = "workflow" schemaVersion = 1 name = "test-spec" workflowId = "%s" -workflowOwner = "%s" -workflowName = "%s" workflow = """ %s """ ` - toml := fmt.Sprintf(template, id, owner, name, spec) - return WorkflowSpec{toml: toml} -} + + toml := fmt.Sprintf(template, id, spec) + j, err := workflows.ValidatedWorkflowJobSpec(toml) + require.NoError(t, err, "failed to validate TOML job spec for workflow %s", toml) + return WorkflowJobSpec{toml: toml, j: j} +} + +func DefaultWorkflowJobSpec(t *testing.T) WorkflowJobSpec { + return GenerateWorkflowJobSpec(t, defaultWFYamlSpec) +} + +var defaultWFYamlSpec = ` +name: "myworkflow" +owner: "0x00000000000000000000000000000000000000aa" +triggers: + - id: "a-trigger@1.0.0" + config: {} + +actions: + - id: "an-action@1.0.0" + ref: "an-action" + config: {} + inputs: + trigger_output: $(trigger.outputs) + +consensus: + - id: "a-consensus@1.0.0" + ref: "a-consensus" + config: {} + inputs: + trigger_output: $(trigger.outputs) + an-action_output: $(an-action.outputs) + +targets: + - id: "a-target@1.0.0" + config: {} + ref: "a-target" + inputs: + consensus_output: $(a-consensus.outputs) +` diff --git a/core/utils/deferable_write_closer_test.go b/core/utils/deferable_write_closer_test.go index ef03acf9d6..18d08bd80c 100644 --- a/core/utils/deferable_write_closer_test.go +++ b/core/utils/deferable_write_closer_test.go @@ -1,6 +1,7 @@ package utils import ( + "io" "os" "path/filepath" "testing" @@ -16,7 +17,7 @@ func TestDeferableWriteCloser_Close(t *testing.T) { wc := NewDeferableWriteCloser(f) wantStr := "wanted" - _, err = wc.Write([]byte(wantStr)) + _, err = io.WriteString(wc, wantStr) assert.NoError(t, err) defer func() { assert.NoError(t, wc.Close()) @@ -27,10 +28,10 @@ func TestDeferableWriteCloser_Close(t *testing.T) { // safe to close multiple times assert.NoError(t, wc.Close()) - _, err = f.Write([]byte("after close")) + _, err = io.WriteString(f, "after close") assert.ErrorIs(t, err, os.ErrClosed) - _, err = wc.Write([]byte("write to wc after close")) + _, err = io.WriteString(f, "write to wc after close") assert.ErrorIs(t, err, os.ErrClosed) r, err := os.ReadFile(f.Name()) diff --git a/core/web/assets/index.html b/core/web/assets/index.html index c08e2a365a..eb81b6d994 100644 --- a/core/web/assets/index.html +++ b/core/web/assets/index.html @@ -1 +1 @@ -Operator UIChainlink
\ No newline at end of file +Operator UIChainlink
\ No newline at end of file diff --git a/core/web/assets/index.html.gz b/core/web/assets/index.html.gz index bdd02aa740..009ac43692 100644 Binary files a/core/web/assets/index.html.gz and b/core/web/assets/index.html.gz differ diff --git a/core/web/assets/main.d14a79e7e016a7c6b5f5.js b/core/web/assets/main.026013f04da39527a75d.js similarity index 93% rename from core/web/assets/main.d14a79e7e016a7c6b5f5.js rename to core/web/assets/main.026013f04da39527a75d.js index 253a0178c1..e3e27950a6 100644 --- a/core/web/assets/main.d14a79e7e016a7c6b5f5.js +++ b/core/web/assets/main.026013f04da39527a75d.js @@ -168,7 +168,7 @@ object-assign * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nOj});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var os=n(59067),ou=n(28428),oc=n(11186),ol=n(78513);function of(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var od=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:of({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oh=(0,b.withStyles)(od)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),op=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},ob=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},om=(0,b.withStyles)(od)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function og(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sq=sV;function sZ(e,t){var n=this.__data__,r=sH(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sX=sZ;function sJ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cC}let cD=cI;var cN="[object Arguments]",cP="[object Array]",cR="[object Boolean]",cj="[object Date]",cF="[object Error]",cY="[object Function]",cB="[object Map]",cU="[object Number]",cH="[object Object]",c$="[object RegExp]",cz="[object Set]",cG="[object String]",cW="[object WeakMap]",cK="[object ArrayBuffer]",cV="[object DataView]",cq="[object Float64Array]",cZ="[object Int8Array]",cX="[object Int16Array]",cJ="[object Int32Array]",cQ="[object Uint8Array]",c1="[object Uint8ClampedArray]",c0="[object Uint16Array]",c2="[object Uint32Array]",c3={};function c4(e){return eD(e)&&cD(e.length)&&!!c3[eC(e)]}c3["[object Float32Array]"]=c3[cq]=c3[cZ]=c3[cX]=c3[cJ]=c3[cQ]=c3[c1]=c3[c0]=c3[c2]=!0,c3[cN]=c3[cP]=c3[cK]=c3[cR]=c3[cV]=c3[cj]=c3[cF]=c3[cY]=c3[cB]=c3[cU]=c3[cH]=c3[c$]=c3[cz]=c3[cG]=c3[cW]=!1;let c6=c4;function c5(e){return function(t){return e(t)}}let c8=c5;var c9=n(79730),c7=c9.Z&&c9.Z.isTypedArray,le=c7?c8(c7):c6;let lt=le;var ln=Object.prototype.hasOwnProperty;function lr(e,t){var n=cx(e),r=!n&&cS(e),i=!n&&!r&&(0,cT.Z)(e),a=!n&&!r&&!i&<(e),o=n||r||i||a,s=o?cb(e.length,String):[],u=s.length;for(var c in e)(t||ln.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cL(c,u)))&&s.push(c);return s}let li=lr;var la=Object.prototype;function lo(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||la)}let ls=lo;var lu=sT(Object.keys,Object);let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ls(e))return lc(e);var t=[];for(var n in Object(e))ll.call(e,n)&&"constructor"!=n&&t.push(n);return t}let ld=lf;function lh(e){return null!=e&&cD(e.length)&&!ur(e)}let lp=lh;function lb(e){return lp(e)?li(e):ld(e)}let lm=lb;function lg(e,t){return e&&ch(t,lm(t),e)}let lv=lg;function ly(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lw=ly;var l_=Object.prototype.hasOwnProperty;function lE(e){if(!ed(e))return lw(e);var t=ls(e),n=[];for(var r in e)"constructor"==r&&(t||!l_.call(e,r))||n.push(r);return n}let lS=lE;function lk(e){return lp(e)?li(e,!0):lS(e)}let lx=lk;function lT(e,t){return e&&ch(t,lx(t),e)}let lM=lT;var lO=n(42896);function lA(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hu(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hc=function(e){return Array.isArray(e)&&0===e.length},hl=function(e){return"function"==typeof e},hf=function(e){return null!==e&&"object"==typeof e},hd=function(e){return String(Math.floor(Number(e)))===e},hh=function(e){return"[object String]"===Object.prototype.toString.call(e)},hp=function(e){return 0===l.Children.count(e)},hb=function(e){return hf(e)&&hl(e.then)};function hm(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hv(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hm(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hg(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sk.all([t,n,r],{arrayMerge:hL})})},[h.validate,h.validationSchema,T,S,k]),O=hN(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sd()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sd()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hb(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sd()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hS,E({type:"SET_ERRORS",payload:h.initialErrors||hS}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hk,E({type:"SET_TOUCHED",payload:h.initialTouched||hk}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hN(function(e){if(y.current[e]&&hl(y.current[e].validate)){var t=hm(_.values,e),n=y.current[e].validate(t);return hb(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hN(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hN(function(e,t){var r=hl(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hN(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hg(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hh(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hI(hm(_.values,r),l,c):d?hC(f):c}r&&j(r,i)},[j,_.values]),Y=hN(function(e){if(hh(e))return function(t){return F(t,e)};F(e)}),B=hN(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hN(function(e){if(hh(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hl(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hN(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hN(function(){return f(_.values,V)}),Z=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hm(_.values,e),error:hm(_.errors,e),touched:!!hm(_.touched,e),initialValue:hm(p.current,e),initialTouched:!!hm(m.current,e),initialError:hm(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hf(e),n=t?e.name:e,r=hm(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sd()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hl(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ha({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hT(e){var t=hx(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hw,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hl(r)?r(t):hp(r)?null:l.Children.only(r):null)}function hM(e){var t={};if(e.inner){if(0===e.inner.length)return hg(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hm(t,o.path)||(t=hg(t,o.path,o.message))}}return t}function hO(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hA(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hA(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sR(e)?hA(e):""!==e?e:void 0}):sR(e[r])?t[r]=hA(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hL(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sk(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sk(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hC(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hI(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hD="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hN(e){var t=(0,l.useRef)(e);return hD(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ha({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hg(n.values,a,e(hm(n.values,a))),u=r?i(hm(n.errors,a)):void 0,c=t?o(hm(n.touched,a)):void 0;return hc(u)&&(u=void 0),hc(c)&&(c=void 0),ha({},n,{values:s,errors:r?hg(n.errors,a,u):n.errors,touched:t?hg(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hU(t),[hi(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hj(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},function(t){return hY(t,e,null)},function(t){return hY(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hu(n)),n.pop=n.pop.bind(hu(n)),n}ho(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sd()(hm(e.formik.values,e.name),hm(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hU(n):[];return t||(t=r[e]),hl(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hs(t.formik,["validate","validationSchema"]),s=ha({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hp(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hH=n(24802),h$=n(71209),hz=n(91750),hG=n(11970),hW=n(4689),hK=n(67598),hV=function(){return(hV=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hq(e,["disabled","field","form","onBlur","helperText"]),d=hm(u,i.name),h=hm(s,i.name)&&!!d;return hV(hV({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hX(e){var t=e.children,n=hq(e,["children"]);return(0,l.createElement)(iw.Z,hV({},hZ(n)),t)}function hJ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hQ(e){return(0,l.createElement)(hH.Z,hV({},hJ(e)))}function h1(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hq(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h0(e){return(0,l.createElement)(h$.Z,hV({},h1(e)))}function h2(e){var t=e.Label,n=hq(e,["Label"]);return(0,l.createElement)(hz.Z,hV({control:(0,l.createElement)(h$.Z,hV({},h1(n)))},t))}function h3(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h4(e){return(0,l.createElement)(hG.default,hV({},h3(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hq(t,["onBlur"]),i=(e.form,e.onBlur),a=hq(e,["field","form","onBlur"]);return hV(hV({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h5(e){return(0,l.createElement)(hW.Z,hV({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h9(e){return(0,l.createElement)(hK.default,hV({},h8(e)))}hX.displayName="FormikMaterialUITextField",hQ.displayName="FormikMaterialUISwitch",h0.displayName="FormikMaterialUICheckbox",h2.displayName="FormikMaterialUICheckboxWithLabel",h4.displayName="FormikMaterialUISelect",h5.displayName="FormikMaterialUIRadioGroup",h9.displayName="FormikMaterialUIInputBase";try{a=Map}catch(h7){}try{o=Set}catch(pe){}function pt(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pn);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pt(e[i],t,n)}return r}return e}function pn(e){return pt(e,[],[])}let pr=Object.prototype.toString,pi=Error.prototype.toString,pa=RegExp.prototype.toString,po="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",ps=/^Symbol\((.*)\)(.*)$/;function pu(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pc(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pu(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return po.call(e).replace(ps,"Symbol($1)");let r=pr.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pi.call(e)+"]":"RegExp"===r?pa.call(e):null}function pl(e,t){let n=pc(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pc(this[e],t);return null!==r?r:n},2)}let pf={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pl(n,!0)}\``+(i?` (cast from the value \`${pl(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pd={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},ph={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pp={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pb={isValue:"${path} field must be ${value}"},pm={noUnknown:"${path} field has unspecified keys: ${unknown}"},pg={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pf,string:pd,number:ph,date:pp,object:pm,array:pg,boolean:pb});var pv=n(18721),py=n.n(pv);let pw=e=>e&&e.__isYupSchema__;class p_{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!py()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pw(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pE=p_;function pS(e){return null==e?[]:[].concat(e)}function pk(){return(pk=Object.assign||function(e){for(var t=1;tpl(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pS(e).forEach(e=>{pT.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pT)}}let pM=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pO(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pM(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pT(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pR(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pP(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pD.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pL()(pN({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pT(pT.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pN({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pT.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pT.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pD.prototype.__isYupRef=!0;let pj=e=>e.substr(0,e.length-1).substr(1);function pF(e,t,n,r=n){let i,a,o;return t?((0,pC.forEach)(t,(s,u,c)=>{let l=u?pj(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pY{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pD.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pD.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pY;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pB(){return(pB=Object.assign||function(e){for(var t=1;t{this.typeError(pf.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pB({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pB({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pn(pB({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pB({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pB({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pl(e),a=pl(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". + */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nOW});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var os=n(59067),ou=n(28428),oc=n(11186),ol=n(78513);function of(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var od=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:of({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oh=(0,b.withStyles)(od)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),op=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},ob=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},om=(0,b.withStyles)(od)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function og(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sq=sV;function sZ(e,t){var n=this.__data__,r=sH(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sX=sZ;function sJ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cC}let cD=cI;var cN="[object Arguments]",cP="[object Array]",cR="[object Boolean]",cj="[object Date]",cF="[object Error]",cY="[object Function]",cB="[object Map]",cU="[object Number]",cH="[object Object]",c$="[object RegExp]",cz="[object Set]",cG="[object String]",cW="[object WeakMap]",cK="[object ArrayBuffer]",cV="[object DataView]",cq="[object Float64Array]",cZ="[object Int8Array]",cX="[object Int16Array]",cJ="[object Int32Array]",cQ="[object Uint8Array]",c1="[object Uint8ClampedArray]",c0="[object Uint16Array]",c2="[object Uint32Array]",c3={};function c4(e){return eD(e)&&cD(e.length)&&!!c3[eC(e)]}c3["[object Float32Array]"]=c3[cq]=c3[cZ]=c3[cX]=c3[cJ]=c3[cQ]=c3[c1]=c3[c0]=c3[c2]=!0,c3[cN]=c3[cP]=c3[cK]=c3[cR]=c3[cV]=c3[cj]=c3[cF]=c3[cY]=c3[cB]=c3[cU]=c3[cH]=c3[c$]=c3[cz]=c3[cG]=c3[cW]=!1;let c6=c4;function c5(e){return function(t){return e(t)}}let c8=c5;var c9=n(79730),c7=c9.Z&&c9.Z.isTypedArray,le=c7?c8(c7):c6;let lt=le;var ln=Object.prototype.hasOwnProperty;function lr(e,t){var n=cx(e),r=!n&&cS(e),i=!n&&!r&&(0,cT.Z)(e),a=!n&&!r&&!i&<(e),o=n||r||i||a,s=o?cb(e.length,String):[],u=s.length;for(var c in e)(t||ln.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cL(c,u)))&&s.push(c);return s}let li=lr;var la=Object.prototype;function lo(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||la)}let ls=lo;var lu=sT(Object.keys,Object);let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ls(e))return lc(e);var t=[];for(var n in Object(e))ll.call(e,n)&&"constructor"!=n&&t.push(n);return t}let ld=lf;function lh(e){return null!=e&&cD(e.length)&&!ur(e)}let lp=lh;function lb(e){return lp(e)?li(e):ld(e)}let lm=lb;function lg(e,t){return e&&ch(t,lm(t),e)}let lv=lg;function ly(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lw=ly;var l_=Object.prototype.hasOwnProperty;function lE(e){if(!ed(e))return lw(e);var t=ls(e),n=[];for(var r in e)"constructor"==r&&(t||!l_.call(e,r))||n.push(r);return n}let lS=lE;function lk(e){return lp(e)?li(e,!0):lS(e)}let lx=lk;function lT(e,t){return e&&ch(t,lx(t),e)}let lM=lT;var lO=n(42896);function lA(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hu(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hc=function(e){return Array.isArray(e)&&0===e.length},hl=function(e){return"function"==typeof e},hf=function(e){return null!==e&&"object"==typeof e},hd=function(e){return String(Math.floor(Number(e)))===e},hh=function(e){return"[object String]"===Object.prototype.toString.call(e)},hp=function(e){return 0===l.Children.count(e)},hb=function(e){return hf(e)&&hl(e.then)};function hm(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hv(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hm(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hg(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sk.all([t,n,r],{arrayMerge:hL})})},[h.validate,h.validationSchema,T,S,k]),O=hN(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sd()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sd()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hb(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sd()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hS,E({type:"SET_ERRORS",payload:h.initialErrors||hS}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hk,E({type:"SET_TOUCHED",payload:h.initialTouched||hk}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hN(function(e){if(y.current[e]&&hl(y.current[e].validate)){var t=hm(_.values,e),n=y.current[e].validate(t);return hb(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hN(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hN(function(e,t){var r=hl(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hN(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hg(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hh(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hI(hm(_.values,r),l,c):d?hC(f):c}r&&j(r,i)},[j,_.values]),Y=hN(function(e){if(hh(e))return function(t){return F(t,e)};F(e)}),B=hN(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hN(function(e){if(hh(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hl(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hN(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hN(function(){return f(_.values,V)}),Z=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hm(_.values,e),error:hm(_.errors,e),touched:!!hm(_.touched,e),initialValue:hm(p.current,e),initialTouched:!!hm(m.current,e),initialError:hm(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hf(e),n=t?e.name:e,r=hm(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sd()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hl(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ha({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hT(e){var t=hx(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hw,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hl(r)?r(t):hp(r)?null:l.Children.only(r):null)}function hM(e){var t={};if(e.inner){if(0===e.inner.length)return hg(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hm(t,o.path)||(t=hg(t,o.path,o.message))}}return t}function hO(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hA(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hA(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sR(e)?hA(e):""!==e?e:void 0}):sR(e[r])?t[r]=hA(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hL(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sk(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sk(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hC(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hI(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hD="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hN(e){var t=(0,l.useRef)(e);return hD(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ha({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hg(n.values,a,e(hm(n.values,a))),u=r?i(hm(n.errors,a)):void 0,c=t?o(hm(n.touched,a)):void 0;return hc(u)&&(u=void 0),hc(c)&&(c=void 0),ha({},n,{values:s,errors:r?hg(n.errors,a,u):n.errors,touched:t?hg(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hU(t),[hi(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hj(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},function(t){return hY(t,e,null)},function(t){return hY(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hu(n)),n.pop=n.pop.bind(hu(n)),n}ho(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sd()(hm(e.formik.values,e.name),hm(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hU(n):[];return t||(t=r[e]),hl(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hs(t.formik,["validate","validationSchema"]),s=ha({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hp(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hH=n(24802),h$=n(71209),hz=n(91750),hG=n(11970),hW=n(4689),hK=n(67598),hV=function(){return(hV=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hq(e,["disabled","field","form","onBlur","helperText"]),d=hm(u,i.name),h=hm(s,i.name)&&!!d;return hV(hV({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hX(e){var t=e.children,n=hq(e,["children"]);return(0,l.createElement)(iw.Z,hV({},hZ(n)),t)}function hJ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hQ(e){return(0,l.createElement)(hH.Z,hV({},hJ(e)))}function h1(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hq(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h0(e){return(0,l.createElement)(h$.Z,hV({},h1(e)))}function h2(e){var t=e.Label,n=hq(e,["Label"]);return(0,l.createElement)(hz.Z,hV({control:(0,l.createElement)(h$.Z,hV({},h1(n)))},t))}function h3(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h4(e){return(0,l.createElement)(hG.default,hV({},h3(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hq(t,["onBlur"]),i=(e.form,e.onBlur),a=hq(e,["field","form","onBlur"]);return hV(hV({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h5(e){return(0,l.createElement)(hW.Z,hV({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h9(e){return(0,l.createElement)(hK.default,hV({},h8(e)))}hX.displayName="FormikMaterialUITextField",hQ.displayName="FormikMaterialUISwitch",h0.displayName="FormikMaterialUICheckbox",h2.displayName="FormikMaterialUICheckboxWithLabel",h4.displayName="FormikMaterialUISelect",h5.displayName="FormikMaterialUIRadioGroup",h9.displayName="FormikMaterialUIInputBase";try{a=Map}catch(h7){}try{o=Set}catch(pe){}function pt(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pn);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pt(e[i],t,n)}return r}return e}function pn(e){return pt(e,[],[])}let pr=Object.prototype.toString,pi=Error.prototype.toString,pa=RegExp.prototype.toString,po="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",ps=/^Symbol\((.*)\)(.*)$/;function pu(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pc(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pu(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return po.call(e).replace(ps,"Symbol($1)");let r=pr.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pi.call(e)+"]":"RegExp"===r?pa.call(e):null}function pl(e,t){let n=pc(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pc(this[e],t);return null!==r?r:n},2)}let pf={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pl(n,!0)}\``+(i?` (cast from the value \`${pl(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pd={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},ph={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pp={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pb={isValue:"${path} field must be ${value}"},pm={noUnknown:"${path} field has unspecified keys: ${unknown}"},pg={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pf,string:pd,number:ph,date:pp,object:pm,array:pg,boolean:pb});var pv=n(18721),py=n.n(pv);let pw=e=>e&&e.__isYupSchema__;class p_{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!py()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pw(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pE=p_;function pS(e){return null==e?[]:[].concat(e)}function pk(){return(pk=Object.assign||function(e){for(var t=1;tpl(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pS(e).forEach(e=>{pT.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pT)}}let pM=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pO(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pM(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pT(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pR(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pP(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pD.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pL()(pN({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pT(pT.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pN({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pT.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pT.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pD.prototype.__isYupRef=!0;let pj=e=>e.substr(0,e.length-1).substr(1);function pF(e,t,n,r=n){let i,a,o;return t?((0,pC.forEach)(t,(s,u,c)=>{let l=u?pj(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pY{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pD.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pD.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pY;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pB(){return(pB=Object.assign||function(e){for(var t=1;t{this.typeError(pf.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pB({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pB({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pn(pB({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pB({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pB({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pl(e),a=pl(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". attempted value: ${i} -`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))},xc=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xl=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xc,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xf=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:r,onSubmit:n})))))};function xd(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xh(){var e=xd(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xh=function(){return e},e}var xp=n0(xh()),xb=function(){return rv(xp)};function xm(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(xq,e)};function xX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TU,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},T$={name:"Chainlink Feeds Manager",uri:"",publicKey:""},Tz=function(e){var t=e.onSubmit;return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Register Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:T$,onSubmit:t})))))};function TG(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return Mh(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?Mv[c.action].title:"",body:c?Mv[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Mr,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function Mw(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function M_(){var e=Mw(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return M_=function(){return e},e}var ME=n0(M_(),Mm),MS=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(T8,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(TB,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(My,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Mk(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.nextNonce&&t.append("nextNonce",e.nextNonce),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file +`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))},xc=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xl=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xc,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xf=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:r,onSubmit:n})))))};function xd(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xh(){var e=xd(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xh=function(){return e},e}var xp=n0(xh()),xb=function(){return rv(xp)};function xm(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function xF(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function xY(e,t){return xD(e)||xP(e,t)||xB(e,t)||xR()}function xB(e,t){if(e){if("string"==typeof e)return xI(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return xI(e,t)}}var xU=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},xH=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0().required("Required"),ocr1Multiaddr:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr1P2PPeerID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr1KeyBundleID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2Multiaddr:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr2P2PPeerID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2KeyBundleID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pV().required("Required"),ocr2ExecutePluginEnabled:pV().required("Required"),ocr2MedianPluginEnabled:pV().required("Required"),ocr2MercuryPluginEnabled:pV().required("Required"),ocr2ForwarderAddress:p0().nullable()}),x$=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},xz=function(e){var t=e.chainAccounts,n=xj(e,["chainAccounts"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=xY(l.useState(!1),2),c=u[0],f=u[1],d=l.useRef();l.useEffect(function(){d.current=a},[a]),l.useEffect(function(){a!==d.current&&(s(n.name,""),f(!1))},[a,s,n.name]);var h=function(e){var t=e.target.value;"custom"===t?(f(!0),s(n.name,"")):(f(!1),s(n.name,t))};return l.createElement(l.Fragment,null,!xU(a)&&l.createElement(hP,xN({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e.address,value:e.address},e.address)})),xU(a)&&l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),xU(a)&&l.createElement("div",null,l.createElement(hP,{component:hX,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},xG=(0,b.withStyles)(x$)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chainIDs,u=void 0===s?[]:s,c=e.accounts,f=void 0===c?[]:c,h=e.p2pKeys,p=void 0===h?[]:h,b=e.ocrKeys,m=void 0===b?[]:b,g=e.ocr2Keys,v=void 0===g?[]:g,y=e.showSubmit,w=void 0!==y&&y;return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:xH,onSubmit:o},function(e){var n=e.values,i=f.filter(function(e){return e.chain.id==n.chainID&&!e.isDisabled});return l.createElement(hR,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:!0},l.createElement(tE.default,{key:"EVM",value:"EVM"},"EVM"))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},u.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(xz,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",chainAccounts:i,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",required:!0,fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),n.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),n.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},p.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},m.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),n.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),n.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},p.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},v.filter(function(e){return n.chainType===e.chainType}).map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hP,{component:hX,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),w&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})}),xW=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_K({fetchPolicy:"cache-and-network"}).data,s=SV({fetchPolicy:"cache-and-network"}).data,u=EO({fetchPolicy:"cache-and-network"}).data,c=E2({fetchPolicy:"cache-and-network"}).data,f={chainID:"",chainType:"EVM",accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},d=a?a.chains.results.map(function(e){return e.id}):[],h=o?o.ethKeys.results:[],p=s?s.p2pKeys.results:[],b=u?u.ocrKeyBundles.results:[],m=c?c.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(oT.Z,null,l.createElement(xG,{innerRef:i,initialValues:f,onSubmit:r,chainIDs:d,accounts:h,p2pKeys:p,ocrKeys:b,ocr2Keys:m})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:t},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},xK=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_K({fetchPolicy:"cache-and-network"}).data,u=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var d={chainID:t.chainID,chainType:"EVM",accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},h=o?o.chains.results.map(function(e){return e.id}):[],p=s?s.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(oT.Z,null,l.createElement(xG,{innerRef:a,initialValues:d,onSubmit:i,chainIDs:h,accounts:p,p2pKeys:b,ocrKeys:m,ocr2Keys:g,editing:!0})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:n},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function xV(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xq(){var e=xV(["\n fragment FeedsManager_ChainConfigFields on FeedsManagerChainConfig {\n id\n chainID\n chainType\n accountAddr\n adminAddr\n accountAddrPubKey\n fluxMonitorJobConfig {\n enabled\n }\n ocr1JobConfig {\n enabled\n isBootstrap\n multiaddr\n p2pPeerID\n keyBundleID\n }\n ocr2JobConfig {\n enabled\n isBootstrap\n multiaddr\n forwarderAddress\n p2pPeerID\n keyBundleID\n plugins {\n commit\n execute\n median\n mercury\n rebalancer\n }\n }\n }\n"]);return xq=function(){return e},e}function xZ(){var e=xV(["\n ","\n fragment FeedsManagerFields on FeedsManager {\n id\n name\n uri\n publicKey\n isConnectionActive\n chainConfigs {\n ...FeedsManager_ChainConfigFields\n }\n }\n"]);return xZ=function(){return e},e}function xX(){var e=xV(["\n fragment FeedsManager_JobProposalsFields on JobProposal {\n id\n name\n externalJobID\n remoteUUID\n status\n pendingUpdate\n latestSpec {\n createdAt\n version\n }\n }\n"]);return xX=function(){return e},e}function xJ(){var e=xV(["\n ","\n ","\n fragment FeedsManagerPayload_ResultsFields on FeedsManager {\n ...FeedsManagerFields\n jobProposals {\n ...FeedsManager_JobProposalsFields\n }\n }\n"]);return xJ=function(){return e},e}function xQ(){var e=xV(["\n ","\n query FetchFeedManagersWithProposals {\n feedsManagers {\n results {\n ...FeedsManagerPayload_ResultsFields\n }\n }\n }\n"]);return xQ=function(){return e},e}var x1=n0(xq()),x0=n0(xZ(),x1),x2=n0(xX()),x3=n0(xJ(),x0,x2),x4=n0(xQ(),x3),x6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(x4,e)};function x5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TZ,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},TJ={name:"Chainlink Feeds Manager",uri:"",publicKey:""},TQ=function(e){var t=e.onSubmit;return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Register Feeds Manager"}),l.createElement(aW.Z,null,l.createElement(xl,{initialValues:TJ,onSubmit:t})))))};function T1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return ME(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?MM[c.action].title:"",body:c?MM[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Md,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function MA(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ML(){var e=MA(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return ML=function(){return e},e}var MC=n0(ML(),Mx),MI=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(Mo,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(Tq,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(MO,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function MD(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.nextNonce&&t.append("nextNonce",e.nextNonce),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file diff --git a/core/web/assets/main.d14a79e7e016a7c6b5f5.js.gz b/core/web/assets/main.026013f04da39527a75d.js.gz similarity index 86% rename from core/web/assets/main.d14a79e7e016a7c6b5f5.js.gz rename to core/web/assets/main.026013f04da39527a75d.js.gz index f16490ab26..8524ee8d01 100644 Binary files a/core/web/assets/main.d14a79e7e016a7c6b5f5.js.gz and b/core/web/assets/main.026013f04da39527a75d.js.gz differ diff --git a/core/web/bridge_types_controller_test.go b/core/web/bridge_types_controller_test.go index e964114e7e..d425d82156 100644 --- a/core/web/bridge_types_controller_test.go +++ b/core/web/bridge_types_controller_test.go @@ -258,7 +258,7 @@ func TestBridgeTypesController_Update_Success(t *testing.T) { require.NoError(t, app.BridgeORM().CreateBridgeType(ctx, bt)) body := fmt.Sprintf(`{"name": "%s","url":"http://yourbridge"}`, bridgeName) - ud := bytes.NewBuffer([]byte(body)) + ud := bytes.NewBufferString(body) resp, cleanup := client.Patch("/v2/bridge_types/"+bridgeName, ud) t.Cleanup(cleanup) cltest.AssertServerResponse(t, resp, http.StatusOK) diff --git a/core/web/cosmos_chains_controller.go b/core/web/cosmos_chains_controller.go index 56ae007128..27c3976ce3 100644 --- a/core/web/cosmos_chains_controller.go +++ b/core/web/cosmos_chains_controller.go @@ -1,15 +1,15 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) func NewCosmosChainsController(app chainlink.Application) ChainsController { return newChainsController[presenters.CosmosChainResource]( - types.NetworkCosmos, - app.GetRelayers().List(chainlink.FilterRelayersByType(types.NetworkCosmos)), + relay.NetworkCosmos, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkCosmos)), ErrCosmosNotEnabled, presenters.NewCosmosChainResource, app.GetLogger(), diff --git a/core/web/cosmos_nodes_controller.go b/core/web/cosmos_nodes_controller.go index c384c10247..f3a226721c 100644 --- a/core/web/cosmos_nodes_controller.go +++ b/core/web/cosmos_nodes_controller.go @@ -1,8 +1,8 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -10,7 +10,7 @@ import ( var ErrCosmosNotEnabled = errChainDisabled{name: "Cosmos", tomlKey: "Cosmos.Enabled"} func NewCosmosNodesController(app chainlink.Application) NodesController { - scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), types.NetworkCosmos) + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkCosmos) return newNodesController[presenters.CosmosNodeResource]( scopedNodeStatuser, ErrCosmosNotEnabled, presenters.NewCosmosNodeResource, app.GetAuditLogger(), diff --git a/core/web/cosmos_transfer_controller.go b/core/web/cosmos_transfer_controller.go index d0de1fd727..ea2c1cfa2a 100644 --- a/core/web/cosmos_transfer_controller.go +++ b/core/web/cosmos_transfer_controller.go @@ -14,6 +14,7 @@ import ( coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/db" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/denom" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -28,7 +29,7 @@ type CosmosTransfersController struct { // Create sends native coins from the Chainlink's account to a specified address. func (tc *CosmosTransfersController) Create(c *gin.Context) { - relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(types.NetworkCosmos)) + relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkCosmos)) if relayers == nil { jsonAPIError(c, http.StatusBadRequest, ErrSolanaNotEnabled) return @@ -48,7 +49,7 @@ func (tc *CosmosTransfersController) Create(c *gin.Context) { return } - relayerID := types.RelayID{Network: types.NetworkCosmos, ChainID: tr.CosmosChainID} + relayerID := types.RelayID{Network: relay.NetworkCosmos, ChainID: tr.CosmosChainID} relayer, err := relayers.Get(relayerID) if err != nil { if errors.Is(err, chainlink.ErrNoSuchRelayer) { diff --git a/core/web/evm_chains_controller.go b/core/web/evm_chains_controller.go index 3d939a9f9b..9c887fa409 100644 --- a/core/web/evm_chains_controller.go +++ b/core/web/evm_chains_controller.go @@ -1,8 +1,8 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -10,8 +10,8 @@ var ErrEVMNotEnabled = errChainDisabled{name: "EVM", tomlKey: "EVM.Enabled"} func NewEVMChainsController(app chainlink.Application) ChainsController { return newChainsController[presenters.EVMChainResource]( - types.NetworkEVM, - app.GetRelayers().List(chainlink.FilterRelayersByType(types.NetworkEVM)), + relay.NetworkEVM, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkEVM)), ErrEVMNotEnabled, presenters.NewEVMChainResource, app.GetLogger(), diff --git a/core/web/evm_nodes_controller.go b/core/web/evm_nodes_controller.go index ba8e112c36..8872f51d7e 100644 --- a/core/web/evm_nodes_controller.go +++ b/core/web/evm_nodes_controller.go @@ -1,13 +1,13 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) func NewEVMNodesController(app chainlink.Application) NodesController { - scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), types.NetworkEVM) + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkEVM) return newNodesController[presenters.EVMNodeResource]( scopedNodeStatuser, ErrEVMNotEnabled, presenters.NewEVMNodeResource, app.GetAuditLogger()) diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index fff30a7df3..ccb2f0774c 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -268,7 +268,7 @@ func TestTransfersController_JSONBindingError(t *testing.T) { client := app.NewHTTPClient(nil) - resp, cleanup := client.Post("/v2/transfers", bytes.NewBuffer([]byte(`{"address":""}`))) + resp, cleanup := client.Post("/v2/transfers", bytes.NewBufferString(`{"address":""}`)) t.Cleanup(cleanup) cltest.AssertServerResponse(t, resp, http.StatusBadRequest) diff --git a/core/web/health_controller_test.go b/core/web/health_controller_test.go index 547186e33f..21da1fb2e4 100644 --- a/core/web/health_controller_test.go +++ b/core/web/health_controller_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "io" "net/http" + "strings" "testing" "github.com/gin-gonic/gin" @@ -127,7 +128,7 @@ func TestHealthController_Health_body(t *testing.T) { require.NoError(t, json.Indent(&b, body, "", " ")) body = b.Bytes() } - assert.Equal(t, tc.expBody, string(body)) + assert.Equal(t, strings.TrimSpace(tc.expBody), strings.TrimSpace(string(body))) }) } } diff --git a/core/web/jobs_controller.go b/core/web/jobs_controller.go index da01d8f7b4..2e005d6d23 100644 --- a/core/web/jobs_controller.go +++ b/core/web/jobs_controller.go @@ -128,7 +128,7 @@ func (jc *JobsController) Create(c *gin.Context) { if err == nil { jc.App.GetAuditLogger().Audit(audit.JobCreated, map[string]interface{}{"job": string(jbj)}) } else { - jc.App.GetLogger().Errorf("Could not send audit log for JobCreation", "err", err) + jc.App.GetLogger().Errorw("Could not send audit log for JobCreation", "err", err) } jsonAPIResponse(c, presenters.NewJobResource(jb), jb.Type.String()) @@ -255,7 +255,7 @@ func (jc *JobsController) validateJobSpec(ctx context.Context, tomlString string case job.Stream: jb, err = streams.ValidatedStreamSpec(tomlString) case job.Workflow: - jb, err = workflows.ValidatedWorkflowSpec(tomlString) + jb, err = workflows.ValidatedWorkflowJobSpec(tomlString) case job.StandardCapabilities: jb, err = standardcapabilities.ValidatedStandardCapabilitiesSpec(tomlString) diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 88ebdce293..0401dbdb8c 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -392,9 +392,6 @@ func TestJobController_Create_HappyPath(t *testing.T) { { name: "workflow", tomlTemplate: func(_ string) string { - id := "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" - owner := "00000000000000000000000000000000000000aa" - name := "myworkflow" // 10 bytes workflow := ` triggers: - id: "mercury-trigger@1.0.0" @@ -442,7 +439,7 @@ targets: params: ["$(report)"] abi: "receive(report bytes)" ` - return testspecs.GenerateWorkflowSpec(id, owner, name, workflow).Toml() + return testspecs.GenerateWorkflowJobSpec(t, workflow).Toml() }, assertion: func(t *testing.T, nameAndExternalJobID string, r *http.Response) { require.Equal(t, http.StatusOK, r.StatusCode) diff --git a/core/web/loader/node.go b/core/web/loader/node.go index e67f1fd4d4..f9dd105921 100644 --- a/core/web/loader/node.go +++ b/core/web/loader/node.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) type nodeBatcher struct { @@ -22,7 +23,7 @@ func (b *nodeBatcher) loadByChainIDs(ctx context.Context, keys dataloader.Keys) evmrelayIDs := make([]types.RelayID, 0, len(keys)) for ix, key := range keys { - rid := types.RelayID{Network: types.NetworkEVM, ChainID: key.String()} + rid := types.RelayID{Network: relay.NetworkEVM, ChainID: key.String()} evmrelayIDs = append(evmrelayIDs, rid) keyOrder[key.String()] = ix } diff --git a/core/web/middleware.go b/core/web/middleware.go index 17bd7e65eb..6e9378e618 100644 --- a/core/web/middleware.go +++ b/core/web/middleware.go @@ -21,7 +21,7 @@ import ( // inside this module. To achieve this, we direct webpack to output all of the compiled assets // in this module's folder under the "assets" directory. -//go:generate ../../operator_ui/install.sh +//go:generate go run ../../operator_ui/install.go ../.. //go:embed "assets" var uiEmbedFs embed.FS diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 08b435e82c..288d8133db 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -1060,7 +1060,7 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct { case job.Gateway: jb, err = gateway.ValidatedGatewaySpec(args.Input.TOML) case job.Workflow: - jb, err = workflows.ValidatedWorkflowSpec(args.Input.TOML) + jb, err = workflows.ValidatedWorkflowJobSpec(args.Input.TOML) case job.StandardCapabilities: jb, err = standardcapabilities.ValidatedStandardCapabilitiesSpec(args.Input.TOML) default: diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 573d74fcd5..2d5dcc71d1 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -19,6 +19,7 @@ import ( ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" clnull "github.com/smartcontractkit/chainlink/v2/core/null" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/services/signatures/secp256k1" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -486,7 +487,7 @@ func TestResolver_OCR2Spec(t *testing.T) { OCRKeyBundleID: null.StringFrom(keyBundleID.String()), MonitoringEndpoint: null.StringFrom("https://monitor.endpoint"), P2PV2Bootstrappers: pq.StringArray{"12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw@localhost:5001"}, - Relay: types.NetworkEVM, + Relay: relay.NetworkEVM, RelayConfig: relayConfig, TransmitterID: null.StringFrom(transmitterAddress.String()), PluginType: types.Median, diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index e8c2faaa45..d5211a5157 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -249,3 +249,8 @@ DefaultBootstrappers = [] DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] + +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 6423ccef36..ec2a99812a 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -260,6 +260,11 @@ DeltaDial = '1m0s' DeltaReconcile = '2s' ListenAddresses = ['foo', 'bar'] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' Enabled = false diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 3807452dee..7ca4311764 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -250,6 +250,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/core/web/solana_chains_controller.go b/core/web/solana_chains_controller.go index ffb39cddba..56d44d600c 100644 --- a/core/web/solana_chains_controller.go +++ b/core/web/solana_chains_controller.go @@ -1,15 +1,15 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) func NewSolanaChainsController(app chainlink.Application) ChainsController { return newChainsController( - types.NetworkSolana, - app.GetRelayers().List(chainlink.FilterRelayersByType(types.NetworkSolana)), + relay.NetworkSolana, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkSolana)), ErrSolanaNotEnabled, presenters.NewSolanaChainResource, app.GetLogger(), diff --git a/core/web/solana_nodes_controller.go b/core/web/solana_nodes_controller.go index b3e03b8c32..71b8f70c5e 100644 --- a/core/web/solana_nodes_controller.go +++ b/core/web/solana_nodes_controller.go @@ -1,8 +1,8 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -10,7 +10,7 @@ import ( var ErrSolanaNotEnabled = errChainDisabled{name: "Solana", tomlKey: "Solana.Enabled"} func NewSolanaNodesController(app chainlink.Application) NodesController { - scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), types.NetworkSolana) + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkSolana) return newNodesController[presenters.SolanaNodeResource]( scopedNodeStatuser, ErrSolanaNotEnabled, presenters.NewSolanaNodeResource, app.GetAuditLogger()) diff --git a/core/web/solana_transfer_controller.go b/core/web/solana_transfer_controller.go index 7885c73bf7..db93401d0d 100644 --- a/core/web/solana_transfer_controller.go +++ b/core/web/solana_transfer_controller.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" solanamodels "github.com/smartcontractkit/chainlink/v2/core/store/models/solana" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -23,7 +24,7 @@ type SolanaTransfersController struct { // Create sends SOL and other native coins from the Chainlink's account to a specified address. func (tc *SolanaTransfersController) Create(c *gin.Context) { - relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(types.NetworkSolana)) + relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkSolana)) if relayers == nil { jsonAPIError(c, http.StatusBadRequest, ErrSolanaNotEnabled) return @@ -48,7 +49,7 @@ func (tc *SolanaTransfersController) Create(c *gin.Context) { } amount := new(big.Int).SetUint64(tr.Amount) - relayerID := types.RelayID{Network: types.NetworkSolana, ChainID: tr.SolanaChainID} + relayerID := types.RelayID{Network: relay.NetworkSolana, ChainID: tr.SolanaChainID} relayer, err := relayers.Get(relayerID) if err != nil { if errors.Is(err, chainlink.ErrNoSuchRelayer) { diff --git a/core/web/starknet_chains_controller.go b/core/web/starknet_chains_controller.go index 35a0689911..eb79ba3f96 100644 --- a/core/web/starknet_chains_controller.go +++ b/core/web/starknet_chains_controller.go @@ -1,15 +1,15 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) func NewStarkNetChainsController(app chainlink.Application) ChainsController { return newChainsController( - types.NetworkStarkNet, - app.GetRelayers().List(chainlink.FilterRelayersByType(types.NetworkStarkNet)), + relay.NetworkStarkNet, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkStarkNet)), ErrStarkNetNotEnabled, presenters.NewStarkNetChainResource, app.GetLogger(), diff --git a/core/web/starknet_nodes_controller.go b/core/web/starknet_nodes_controller.go index 5d059d357f..664b89d03c 100644 --- a/core/web/starknet_nodes_controller.go +++ b/core/web/starknet_nodes_controller.go @@ -1,8 +1,8 @@ package web import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -10,7 +10,7 @@ import ( var ErrStarkNetNotEnabled = errChainDisabled{name: "StarkNet", tomlKey: "Starknet.Enabled"} func NewStarkNetNodesController(app chainlink.Application) NodesController { - scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), types.NetworkStarkNet) + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkStarkNet) return newNodesController[presenters.StarkNetNodeResource]( scopedNodeStatuser, ErrStarkNetNotEnabled, presenters.NewStarkNetNodeResource, app.GetAuditLogger()) diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html index d1b208f4a0..2a1b222753 100644 --- a/core/web/testdata/body/health.html +++ b/core/web/testdata/body/health.html @@ -91,11 +91,14 @@ PipelineORM
- PipelineRunner + PipelineRunner +
+ BridgeCache +
PromReporter
TelemetryManager -
\ No newline at end of file + diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index 3c0117de7e..10415c0abd 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -153,6 +153,15 @@ "output": "" } }, + { + "type": "checks", + "id": "PipelineRunner.BridgeCache", + "attributes": { + "name": "PipelineRunner.BridgeCache", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "PromReporter", @@ -172,4 +181,4 @@ } } ] -} \ No newline at end of file +} diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt index 03a78c22c2..09c8cff6c2 100644 --- a/core/web/testdata/body/health.txt +++ b/core/web/testdata/body/health.txt @@ -16,5 +16,6 @@ ok Mercury.WSRPCPool ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner +ok PipelineRunner.BridgeCache ok PromReporter ok TelemetryManager diff --git a/core/web/user_controller.go b/core/web/user_controller.go index 7dbd6d3764..a7b8a3c068 100644 --- a/core/web/user_controller.go +++ b/core/web/user_controller.go @@ -41,7 +41,7 @@ func (u *UserController) Index(c *gin.Context) { jsonAPIError(c, http.StatusBadRequest, errUnsupportedForAuth) return } - u.App.GetLogger().Errorf("Unable to list users", "err", err) + u.App.GetLogger().Errorw("Unable to list users", "err", err) jsonAPIError(c, http.StatusInternalServerError, err) return } @@ -97,7 +97,7 @@ func (u *UserController) Create(c *gin.Context) { jsonAPIError(c, http.StatusBadRequest, errUnsupportedForAuth) return } - u.App.GetLogger().Errorf("Error creating new API user", "err", err) + u.App.GetLogger().Errorw("Error creating new API user", "err", err) jsonAPIError(c, http.StatusInternalServerError, errors.New("error creating API user")) return } @@ -190,7 +190,7 @@ func (u *UserController) Delete(c *gin.Context) { jsonAPIError(c, http.StatusBadRequest, errUnsupportedForAuth) return } - u.App.GetLogger().Errorf("Error deleting API user", "err", err) + u.App.GetLogger().Errorw("Error deleting API user", "err", err) jsonAPIError(c, http.StatusInternalServerError, errors.New("error deleting API user")) return } diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 90ea9678ce..3de0cc64dd 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1206,6 +1206,33 @@ ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example ListenAddresses is the addresses the peer will listen to on the network in `host:port` form as accepted by `net.Listen()`, but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. +## Capabilities.ExternalRegistry +```toml +[Capabilities.ExternalRegistry] +Address = '0x0' # Example +NetworkID = 'evm' # Default +ChainID = '1' # Default +``` + + +### Address +```toml +Address = '0x0' # Example +``` +Address is the address for the capabilities registry contract. + +### NetworkID +```toml +NetworkID = 'evm' # Default +``` +NetworkID identifies the target network where the remote registry is located. + +### ChainID +```toml +ChainID = '1' # Default +``` +ChainID identifies the target chain id where the remote registry is located. + ## Capabilities.Peering ```toml [Capabilities.Peering] diff --git a/go.md b/go.md index dd17f5207b..dda7192c1a 100644 --- a/go.md +++ b/go.md @@ -3,9 +3,13 @@ flowchart LR subgraph chains chainlink-cosmos - chainlink-evm chainlink-solana chainlink-starknet/relayer + subgraph chainlink-integrations + direction LR + chainlink-integrations/evm/relayer + chainlink-integrations/common + end end subgraph products diff --git a/go.mod b/go.mod index a1d45ad986..1596980fb4 100644 --- a/go.mod +++ b/go.mod @@ -73,8 +73,8 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.17 - github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce + github.com/smartcontractkit/chainlink-automation v1.0.4 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 @@ -87,6 +87,7 @@ require ( github.com/smartcontractkit/wsrpc v0.8.1 github.com/spf13/cast v1.6.0 github.com/stretchr/testify v1.9.0 + github.com/test-go/testify v1.1.4 github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a github.com/tidwall/gjson v1.17.0 github.com/ugorji/go/codec v1.2.12 @@ -304,7 +305,6 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect - github.com/test-go/testify v1.1.4 // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect @@ -353,5 +353,4 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - ) diff --git a/go.sum b/go.sum index 0740282f2e..213b96f3be 100644 --- a/go.sum +++ b/go.sum @@ -1168,10 +1168,10 @@ 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.17 h1:otOlYUnutS8oQBEAi9RLQICqZP0Nxy0k8vOZuSMJa4w= github.com/smartcontractkit/chain-selectors v1.0.17/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= -github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= +github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 h1:6322qmPgHgYF/d/NjjbuZvF0Qfz4Hp+wLtLeS3SA3mI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/.golangci.yml b/integration-tests/.golangci.yml index d22b26b826..897c72d1ec 100644 --- a/integration-tests/.golangci.yml +++ b/integration-tests/.golangci.yml @@ -21,8 +21,8 @@ linters-settings: excludes: - G101 govet: - # report about shadowed variables - check-shadowing: true + enable: + - shadow revive: confidence: 0.8 rules: diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions index 6381da7eaf..7b9e8ab6bf 100644 --- a/integration-tests/.tool-versions +++ b/integration-tests/.tool-versions @@ -2,4 +2,4 @@ golang 1.21.7 k3d 5.4.6 kubectl 1.25.5 nodejs 20.13.1 -golangci-lint 1.55.2 +golangci-lint 1.59.1 diff --git a/integration-tests/LOG_POLLER.md b/integration-tests/LOG_POLLER.md index 3d6f4b78ce..ab46838eb3 100644 --- a/integration-tests/LOG_POLLER.md +++ b/integration-tests/LOG_POLLER.md @@ -121,7 +121,7 @@ Various checks inside the tests have hardcoded timeouts, which might not be suit Sample snippet: ``` gom.Eventually(func(g gomega.Gomega) { - logCountMatches, err := clNodesHaveExpectedLogCount(startBlock, endBlock, testEnv.EVMClient.GetChainID(), totalLogsEmitted, expectedFilters, l, coreLogger, testEnv.ClCluster) + logCountMatches, err := ClNodesHaveExpectedLogCount(startBlock, endBlock int64, chainID *big.Int, expectedLogCount int, expectedFilters []ExpectedFilter, l zerolog.Logger, coreLogger core_logger.SugaredLogger, nodes *test_env.ClCluster) (bool, error) { if err != nil { l.Warn().Err(err).Msg("Error checking if CL nodes have expected log count. Retrying...") } diff --git a/integration-tests/Makefile b/integration-tests/Makefile index 4e977f4061..9a85d52125 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -146,7 +146,37 @@ test_node_migrations_simulated_verbose: .PHONY: test_soak_ocr test_soak_ocr: . ./scripts/check_base64_env_var.sh - go test -v -count=1 -run TestOCRSoak ./soak + go test -v -count=1 -run ^TestOCRSoak$$ ./soak + +.PHONY: test_soak_ocr_reorg_1 +test_soak_ocr_reorg_1: + . ./scripts/check_base64_env_var.sh + go test -v -count=1 -run ^TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled$$ ./soak + +.PHONY: test_soak_ocr_reorg_2 +test_soak_ocr_reorg_2: + . ./scripts/check_base64_env_var.sh + go test -v -count=1 -run ^TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled$$ ./soak + +.PHONY: test_soak_ocr_gas_spike +test_soak_ocr_gas_spike: + . ./scripts/check_base64_env_var.sh + go test -v -count=1 -run ^TestOCRSoak_GasSpike$$ ./soak + +.PHONY: test_soak_ocr_gas_limit_change +test_soak_ocr_gas_limit_change: + . ./scripts/check_base64_env_var.sh + go test -v -count=1 -run ^TestOCRSoak_ChangeBlockGasLimit$$ ./soak + +.PHONY: test_soak_ocr_rpc_down_all_cl_nodes +test_soak_ocr_rpc_down_all_cl_nodes: + . ./scripts/check_base64_env_var.sh + go test -v -count=1 -run ^TestOCRSoak_RPCDownForAllCLNodes$$ ./soak + +.PHONY: test_soak_ocr_rpc_down_half_cl_nodes +test_soak_ocr_rpc_down_half_cl_nodes: + . ./scripts/check_base64_env_var.sh + go test -v -count=1 -run ^TestOCRSoak_RPCDownForHalfCLNodes$$ ./soak .PHONY: test_soak_forwarder_ocr test_soak_forwarder_ocr: diff --git a/integration-tests/README.md b/integration-tests/README.md index 860f075953..d34b4426fd 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -60,3 +60,71 @@ You can see the results of each test in the terminal with normal `go test` outpu ## Running Soak, Performance, Benchmark, and Chaos Tests These tests remain bound to a Kubernetes run environment, and require more complex setup and running instructions not documented here. We endeavor to make these easier to run and configure, but for the time being please seek a member of the QA/Test Tooling team if you want to run these. + +### How to run reorg tests +Run soak/ocr_test.go with reorg below finality and `FinalityTagEnabled=false` + +```bash +make test_soak_ocr_reorg_1 +``` + +Run soak/ocr_test.go with reorg below finality and `FinalityTagEnabled=true`: + +```bash +make test_soak_ocr_reorg_2 +``` + +Run reorg/automation_reorg_test.go with reorg settings: + +1. Use Simulated Geth network and put GethReorgConfig in overrides.toml + + + ```toml + [Network] + selected_networks=["simulated"] + [Network.GethReorgConfig] + enabled = true + depth = 10 + delay_create = "3s" + ``` + +2. Then run the test: + ```bash + make test_reorg_automation + ``` + +Run reorg above finality docker test: + +```bash +go test -v -run ^TestReorgAboveFinality_FinalityTagDisabled$ ./smoke +``` + +### How to run gas simulation tests + +Run soak/ocr_test.go with gas spike: + +```bash +make test_soak_ocr_gas_spike +``` + +Run soak/ocr_test.go with changing gas limit creating block congestion: + +```bash +make test_soak_ocr_gas_limit_change +``` + +Note: you can update gas simulation params for the tests below in in testconfig/ocr.toml + +### How to run tests with RPC node failure + +Run soak/ocr_test.go with RPC network chaos by bringing down network to RPC node for all Chainlink Nodes: + +```bash +make test_soak_ocr_rpc_down_all_cl_nodes +``` + +Run soak/ocr_test.go with RPC network chaos by bringing down network to RPC node for 50 percent of Chainlink Nodes: + +```bash +make test_soak_ocr_rpc_down_half_cl_nodes +``` \ No newline at end of file diff --git a/integration-tests/README_SETH.md b/integration-tests/README_SETH.md index 7d0d31674f..92302ab9ce 100644 --- a/integration-tests/README_SETH.md +++ b/integration-tests/README_SETH.md @@ -461,4 +461,4 @@ Currently, Seth doesn't support splitting non-native tokens between keys. If you 3. **Prepare payload for Multicall contract** that will call `transfer` function on the token contract for each key. 4. **Execute Multicall contract** with the payload prepared in the previous step. -You can find sample code for doing that for LINK token in [actions_seth](./actions/seth/actions.go) file as `SendLinkFundsToDeploymentAddresses()` method. \ No newline at end of file +You can find sample code for doing that for LINK token in [actions](./actions/actions.go) file as `SendLinkFundsToDeploymentAddresses()` method. diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 54b6319107..6c3ae0f606 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -4,152 +4,46 @@ package actions import ( "context" "crypto/ecdsa" - "encoding/json" - "errors" "fmt" "math/big" - "os" "strings" "sync" "testing" "time" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/go-resty/resty/v2" - "github.com/rs/zerolog" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" - "github.com/rs/zerolog/log" + geth "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/rpc" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/testreporters" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" -) + "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -// ContractDeploymentInterval After how many contract actions to wait before starting any more -// Example: When deploying 1000 contracts, stop every ContractDeploymentInterval have been deployed to wait before continuing -var ContractDeploymentInterval = 200 + "github.com/ethereum/go-ethereum/accounts/abi" -// FundChainlinkNodes will fund all of the provided Chainlink nodes with a set amountCreateOCRv2Jobs of native currency -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.FundChainlinkNodes -func FundChainlinkNodes( - nodes []*client.ChainlinkK8sClient, - client blockchain.EVMClient, - amount *big.Float, -) error { - for _, cl := range nodes { - toAddress, err := cl.PrimaryEthAddress() - if err != nil { - return err - } - recipient := common.HexToAddress(toAddress) - msg := ethereum.CallMsg{ - From: common.HexToAddress(client.GetDefaultWallet().Address()), - To: &recipient, - Value: conversions.EtherToWei(amount), - } - gasEstimates, err := client.EstimateGas(msg) - if err != nil { - return err - } - err = client.Fund(toAddress, amount, gasEstimates) - if err != nil { - return err - } - } - return client.WaitForEvents() -} + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/rs/zerolog" -// FundChainlinkNodesAddress will fund all of the provided Chainlink nodes address at given index with a set amount of native currency -func FundChainlinkNodesAddress( - nodes []*client.ChainlinkK8sClient, - client blockchain.EVMClient, - amount *big.Float, - keyIndex int, -) error { - for _, cl := range nodes { - toAddress, err := cl.EthAddresses() - if err != nil { - return err - } - toAddr := common.HexToAddress(toAddress[keyIndex]) - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - err = client.Fund(toAddress[keyIndex], amount, gasEstimates) - if err != nil { - return err - } - } - return client.WaitForEvents() -} + "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" + "github.com/smartcontractkit/seth" -// FundChainlinkNodesAddress will fund all of the provided Chainlink nodes addresses with a set amount of native currency -func FundChainlinkNodesAddresses( - nodes []*client.ChainlinkClient, - client blockchain.EVMClient, - amount *big.Float, -) error { - for _, cl := range nodes { - toAddress, err := cl.EthAddressesForChain(client.GetChainID().String()) - if err != nil { - return err - } - for _, addr := range toAddress { - toAddr := common.HexToAddress(addr) - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - err = client.Fund(addr, amount, gasEstimates) - if err != nil { - return err - } - } - } - return client.WaitForEvents() -} + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/test-go/testify/require" + "math" -// FundChainlinkNodes will fund all of the provided Chainlink nodes with a set amount of native currency -func FundChainlinkNodesLink( - nodes []*client.ChainlinkK8sClient, - blockchain blockchain.EVMClient, - linkToken contracts.LinkToken, - linkAmount *big.Int, -) error { - for _, cl := range nodes { - toAddress, err := cl.PrimaryEthAddress() - if err != nil { - return err - } - err = linkToken.Transfer(toAddress, linkAmount) - if err != nil { - return err - } - } - return blockchain.WaitForEvents() -} + "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" +) // ChainlinkNodeAddresses will return all the on-chain wallet addresses for a set of Chainlink nodes func ChainlinkNodeAddresses(nodes []*client.ChainlinkK8sClient) ([]common.Address, error) { @@ -177,29 +71,6 @@ func ChainlinkNodeAddressesAtIndex(nodes []*client.ChainlinkK8sClient, keyIndex return addresses, nil } -// SetChainlinkAPIPageSize specifies the page size from the Chainlink API, useful for high volume testing -func SetChainlinkAPIPageSize(nodes []*client.ChainlinkK8sClient, pageSize int) { - for _, n := range nodes { - n.SetPageSize(pageSize) - } -} - -// ExtractRequestIDFromJobRun extracts RequestID from job runs response -func ExtractRequestIDFromJobRun(jobDecodeData client.RunsResponseData) ([]byte, error) { - var taskRun client.TaskRun - for _, tr := range jobDecodeData.Attributes.TaskRuns { - if tr.Type == "ethabidecodelog" { - taskRun = tr - } - } - var decodeLogTaskRun *client.DecodeLogTaskRun - if err := json.Unmarshal([]byte(taskRun.Output), &decodeLogTaskRun); err != nil { - return nil, err - } - rqInts := decodeLogTaskRun.RequestID - return rqInts, nil -} - // EncodeOnChainVRFProvingKey encodes uncompressed public VRF key to on-chain representation func EncodeOnChainVRFProvingKey(vrfKey client.VRFKey) ([2]*big.Int, error) { uncompressed := vrfKey.Data.Attributes.Uncompressed @@ -218,219 +89,6 @@ func EncodeOnChainVRFProvingKey(vrfKey client.VRFKey) ([2]*big.Int, error) { return provingKey, nil } -// GetMockserverInitializerDataForOTPE creates mocked weiwatchers data needed for otpe -func GetMockserverInitializerDataForOTPE( - OCRInstances []contracts.OffchainAggregator, - chainlinkNodes []*client.ChainlinkK8sClient, -) (interface{}, error) { - var contractsInfo []ctfClient.ContractInfoJSON - - for index, OCRInstance := range OCRInstances { - contractInfo := ctfClient.ContractInfoJSON{ - ContractVersion: 4, - Path: fmt.Sprintf("contract_%d", index), - Status: "live", - ContractAddress: OCRInstance.Address(), - } - - contractsInfo = append(contractsInfo, contractInfo) - } - - contractsInitializer := ctfClient.HttpInitializer{ - Request: ctfClient.HttpRequest{Path: "/contracts.json"}, - Response: ctfClient.HttpResponse{Body: contractsInfo}, - } - - var nodesInfo []ctfClient.NodeInfoJSON - - for _, chainlink := range chainlinkNodes { - ocrKeys, err := chainlink.MustReadOCRKeys() - if err != nil { - return nil, err - } - nodeInfo := ctfClient.NodeInfoJSON{ - NodeAddress: []string{ocrKeys.Data[0].Attributes.OnChainSigningAddress}, - ID: ocrKeys.Data[0].ID, - } - nodesInfo = append(nodesInfo, nodeInfo) - } - - nodesInitializer := ctfClient.HttpInitializer{ - Request: ctfClient.HttpRequest{Path: "/nodes.json"}, - Response: ctfClient.HttpResponse{Body: nodesInfo}, - } - initializers := []ctfClient.HttpInitializer{contractsInitializer, nodesInitializer} - return initializers, nil -} - -// TeardownSuite tears down networks/clients and environment and creates a logs folder for failed tests in the -// specified path. Can also accept a testreporter (if one was used) to log further results -func TeardownSuite( - t *testing.T, - env *environment.Environment, - chainlinkNodes []*client.ChainlinkK8sClient, - optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics - failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level - grafnaUrlProvider testreporters.GrafanaURLProvider, - clients ...blockchain.EVMClient, -) error { - l := logging.GetTestLogger(t) - if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { - return fmt.Errorf("Error dumping environment logs, leaving environment running for manual retrieval, err: %w", err) - } - // Delete all jobs to stop depleting the funds - err := DeleteAllJobs(chainlinkNodes) - if err != nil { - l.Warn().Msgf("Error deleting jobs %+v", err) - } - - for _, c := range clients { - if c != nil && chainlinkNodes != nil && len(chainlinkNodes) > 0 { - if err := ReturnFunds(chainlinkNodes, c); err != nil { - // This printed line is required for tests that use real funds to propagate the failure - // out to the system running the test. Do not remove - fmt.Println(environment.FAILED_FUND_RETURN) - l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - } else { - l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") - } - // nolint - if c != nil { - err := c.Close() - if err != nil { - return err - } - } - } - - return env.Shutdown() -} - -// TeardownRemoteSuite is used when running a test within a remote-test-runner, like for long-running performance and -// soak tests -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.TeardownRemoteSuite -func TeardownRemoteSuite( - t *testing.T, - namespace string, - chainlinkNodes []*client.ChainlinkK8sClient, - optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics - grafnaUrlProvider testreporters.GrafanaURLProvider, - client blockchain.EVMClient, -) error { - l := logging.GetTestLogger(t) - var err error - if err = testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { - l.Warn().Err(err).Msg("Error writing test report") - } - // Delete all jobs to stop depleting the funds - err = DeleteAllJobs(chainlinkNodes) - if err != nil { - l.Warn().Msgf("Error deleting jobs %+v", err) - } - - if err = ReturnFunds(chainlinkNodes, client); err != nil { - l.Error().Err(err).Str("Namespace", namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - return err -} - -func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { - for _, node := range chainlinkNodes { - if node == nil { - return fmt.Errorf("found a nil chainlink node in the list of chainlink nodes while tearing down: %v", chainlinkNodes) - } - jobs, _, err := node.ReadJobs() - if err != nil { - return fmt.Errorf("error reading jobs from chainlink node, err: %w", err) - } - for _, maps := range jobs.Data { - if _, ok := maps["id"]; !ok { - return fmt.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data) - } - id := maps["id"].(string) - _, err := node.DeleteJob(id) - if err != nil { - return fmt.Errorf("error deleting job from chainlink node, err: %w", err) - } - } - } - return nil -} - -// ReturnFunds attempts to return all the funds from the chainlink nodes and other wallets to the network's default wallet, -// which will always be the first wallet in the list of wallets. If errors are encountered, it will keep trying other wallets -// and return all errors encountered. -func ReturnFunds(chainlinkNodes []*client.ChainlinkK8sClient, blockchainClient blockchain.EVMClient) error { - if blockchainClient == nil { - return fmt.Errorf("blockchain client is nil, unable to return funds from chainlink nodes") - } - log.Info().Msg("Attempting to return Chainlink node funds to default network wallets") - if blockchainClient.NetworkSimulated() { - log.Info().Str("Network Name", blockchainClient.GetNetworkName()). - Msg("Network is a simulated network. Skipping fund return.") - return nil - } - // If we fail to return funds from some addresses, we still want to try to return funds from the rest - encounteredErrors := []error{} - - for _, chainlinkNode := range chainlinkNodes { - fundedKeys, err := chainlinkNode.ExportEVMKeysForChain(blockchainClient.GetChainID().String()) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - for _, key := range fundedKeys { - keyToDecrypt, err := json.Marshal(key) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM - // issues. So we avoid running in parallel; slower, but safer. - decryptedKey, err := keystore.DecryptKey(keyToDecrypt, client.ChainlinkKeyPassword) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - continue - } - err = blockchainClient.ReturnFunds(decryptedKey.PrivateKey) - if err != nil { - encounteredErrors = append(encounteredErrors, err) - log.Error().Err(err).Str("Address", fundedKeys[0].Address).Msg("Error returning funds from Chainlink node") - continue - } - } - } - if err := blockchainClient.WaitForEvents(); err != nil { - encounteredErrors = append(encounteredErrors, err) - } - if len(encounteredErrors) > 0 { - return fmt.Errorf("encountered errors while returning funds: %v", encounteredErrors) - } - return nil -} - -// FundAddresses will fund a list of addresses with an amount of native currency -func FundAddresses(blockchain blockchain.EVMClient, amount *big.Float, addresses ...string) error { - for _, address := range addresses { - toAddr := common.HexToAddress(address) - gasEstimates, err := blockchain.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - if err := blockchain.Fund(address, amount, gasEstimates); err != nil { - return err - } - } - return blockchain.WaitForEvents() -} - // EncodeOnChainExternalJobID encodes external job uuid to on-chain representation func EncodeOnChainExternalJobID(jobID uuid.UUID) [32]byte { var ji [32]byte @@ -438,44 +96,6 @@ func EncodeOnChainExternalJobID(jobID uuid.UUID) [32]byte { return ji } -// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment -// to apply the upgrades -func UpgradeChainlinkNodeVersions( - testEnvironment *environment.Environment, - newImage, newVersion string, - nodes ...*client.ChainlinkK8sClient, -) error { - if newImage == "" || newVersion == "" { - return errors.New("New image and new version is needed to upgrade the node") - } - for _, node := range nodes { - if err := node.UpgradeVersion(testEnvironment, newImage, newVersion); err != nil { - return err - } - } - err := testEnvironment.RunUpdated(len(nodes)) - if err != nil { // Run the new environment and wait for changes to show - return err - } - return client.ReconnectChainlinkNodes(testEnvironment, nodes) -} - -func DeployLINKToken(cd contracts.ContractDeployer) (contracts.LinkToken, error) { - linkToken, err := cd.DeployLinkTokenContract() - if err != nil { - return nil, err - } - return linkToken, err -} - -func DeployMockETHLinkFeed(cd contracts.ContractDeployer, answer *big.Int) (contracts.MockETHLINKFeed, error) { - mockETHLINKFeed, err := cd.DeployMockETHLINKFeed(answer) - if err != nil { - return nil, err - } - return mockETHLINKFeed, err -} - // todo - move to CTF func GenerateWallet() (common.Address, error) { privateKey, err := crypto.GenerateKey() @@ -568,94 +188,981 @@ func WaitForBlockNumberToBe( } } -// todo - move to EVMClient -func RewindSimulatedChainToBlockNumber( - ctx context.Context, +var ContractDeploymentInterval = 200 + +// FundChainlinkNodesFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node +// from root private key. It returns an error if any of the transactions failed. +func FundChainlinkNodesFromRootAddress( + logger zerolog.Logger, client *seth.Client, - rpcURL string, - rewindChainToBlockNumber uint64, - l zerolog.Logger, -) (uint64, error) { - latestBlockNumberBeforeReorg, err := client.Client.BlockNumber(ctx) - if err != nil { - return 0, fmt.Errorf("error getting latest block number: %w", err) + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + amount *big.Float, +) error { + if len(client.PrivateKeys) == 0 { + return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) } - l.Info(). - Str("RPC URL", rpcURL). - Uint64("Latest Block Number before Reorg", latestBlockNumberBeforeReorg). - Uint64("Rewind Chain to Block Number", rewindChainToBlockNumber). - Msg("Performing Reorg on chain by rewinding chain to specific block number") - - _, err = NewRPCRawClient(rpcURL).SetHeadForSimulatedChain(rewindChainToBlockNumber) + return FundChainlinkNodes(logger, client, nodes, client.PrivateKeys[0], amount) +} - if err != nil { - return 0, fmt.Errorf("error making reorg: %w", err) +// FundChainlinkNodes sends native token amount (expressed in human-scale) to each Chainlink Node +// from private key's address. It returns an error if any of the transactions failed. +func FundChainlinkNodes( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + privateKey *ecdsa.PrivateKey, + amount *big.Float, +) error { + keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { + return cl.PrimaryEthAddress() } + return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) +} - latestBlockNumberAfterReorg, err := client.Client.BlockNumber(ctx) - if err != nil { - return 0, fmt.Errorf("error getting latest block number: %w", err) +// FundChainlinkNodesAtKeyIndexFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node +// from root private key.It returns an error if any of the transactions failed. It sends the funds to +// node address at keyIndex (as each node can have multiple addresses). +func FundChainlinkNodesAtKeyIndexFromRootAddress( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + amount *big.Float, + keyIndex int, +) error { + if len(client.PrivateKeys) == 0 { + return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) } - l.Info(). - Uint64("Block Number", latestBlockNumberAfterReorg). - Msg("Latest Block Number after Reorg") - return latestBlockNumberAfterReorg, nil + return FundChainlinkNodesAtKeyIndex(logger, client, nodes, client.PrivateKeys[0], amount, keyIndex) } -func GetRPCUrl(env *test_env.CLClusterTestEnv, chainID int64) (string, error) { - provider, err := env.GetRpcProvider(chainID) - if err != nil { - return "", err - } - return provider.PublicHttpUrls()[0], nil -} +// FundChainlinkNodesAtKeyIndex sends native token amount (expressed in human-scale) to each Chainlink Node +// from private key's address. It returns an error if any of the transactions failed. It sends the funds to +// node address at keyIndex (as each node can have multiple addresses). +func FundChainlinkNodesAtKeyIndex( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + privateKey *ecdsa.PrivateKey, + amount *big.Float, + keyIndex int, +) error { + keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { + toAddress, err := cl.EthAddresses() + if err != nil { + return "", err + } + return toAddress[keyIndex], nil + } + return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) +} + +func fundChainlinkNodesAtAnyKey( + logger zerolog.Logger, + client *seth.Client, + nodes []contracts.ChainlinkNodeWithKeysAndAddress, + privateKey *ecdsa.PrivateKey, + amount *big.Float, + keyAddressFn func(contracts.ChainlinkNodeWithKeysAndAddress) (string, error), +) error { + for _, cl := range nodes { + toAddress, err := keyAddressFn(cl) + if err != nil { + return err + } + + fromAddress, err := privateKeyToAddress(privateKey) + if err != nil { + return err + } + + receipt, err := SendFunds(logger, client, FundsToSendPayload{ + ToAddress: common.HexToAddress(toAddress), + Amount: conversions.EtherToWei(amount), + PrivateKey: privateKey, + }) + if err != nil { + logger.Err(err). + Str("From", fromAddress.Hex()). + Str("To", toAddress). + Msg("Failed to fund Chainlink node") + + return err + } + + txHash := "(none)" + if receipt != nil { + txHash = receipt.TxHash.String() + } + + logger.Info(). + Str("From", fromAddress.Hex()). + Str("To", toAddress). + Str("TxHash", txHash). + Str("Amount", amount.String()). + Msg("Funded Chainlink node") + } + + return nil +} + +type FundsToSendPayload struct { + ToAddress common.Address + Amount *big.Int + PrivateKey *ecdsa.PrivateKey + GasLimit *int64 + GasPrice *big.Int + GasFeeCap *big.Int + GasTipCap *big.Int + TxTimeout *time.Duration +} + +// TODO: move to CTF? +// SendFunds sends native token amount (expressed in human-scale) from address controlled by private key +// to given address. You can override any or none of the following: gas limit, gas price, gas fee cap, gas tip cap. +// Values that are not set will be estimated or taken from config. +func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPayload) (*types.Receipt, error) { + fromAddress, err := privateKeyToAddress(payload.PrivateKey) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithTimeout(context.Background(), client.Cfg.Network.TxnTimeout.Duration()) + nonce, err := client.Client.PendingNonceAt(ctx, fromAddress) + defer cancel() + if err != nil { + return nil, err + } + + var gasLimit int64 + gasLimitRaw, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) + if err != nil { + gasLimit = client.Cfg.Network.TransferGasFee + } else { + gasLimit = int64(gasLimitRaw) + } + + gasPrice := big.NewInt(0) + gasFeeCap := big.NewInt(0) + gasTipCap := big.NewInt(0) + + if payload.GasLimit != nil { + gasLimit = *payload.GasLimit + } + + if client.Cfg.Network.EIP1559DynamicFees { + // if any of the dynamic fees are not set, we need to either estimate them or read them from config + if payload.GasFeeCap == nil || payload.GasTipCap == nil { + // estimation or config reading happens here + txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) + gasFeeCap = txOptions.GasFeeCap + gasTipCap = txOptions.GasTipCap + } + + // override with payload values if they are set + if payload.GasFeeCap != nil { + gasFeeCap = payload.GasFeeCap + } + + if payload.GasTipCap != nil { + gasTipCap = payload.GasTipCap + } + } else { + if payload.GasPrice == nil { + txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) + gasPrice = txOptions.GasPrice + } else { + gasPrice = payload.GasPrice + } + } + + var rawTx types.TxData + + if client.Cfg.Network.EIP1559DynamicFees { + rawTx = &types.DynamicFeeTx{ + Nonce: nonce, + To: &payload.ToAddress, + Value: payload.Amount, + Gas: uint64(gasLimit), + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + } + } else { + rawTx = &types.LegacyTx{ + Nonce: nonce, + To: &payload.ToAddress, + Value: payload.Amount, + Gas: uint64(gasLimit), + GasPrice: gasPrice, + } + } + + signedTx, err := types.SignNewTx(payload.PrivateKey, types.LatestSignerForChainID(big.NewInt(client.ChainID)), rawTx) + + if err != nil { + return nil, errors.Wrap(err, "failed to sign tx") + } + + txTimeout := client.Cfg.Network.TxnTimeout.Duration() + if payload.TxTimeout != nil { + txTimeout = *payload.TxTimeout + } + + logger.Debug(). + Str("From", fromAddress.Hex()). + Str("To", payload.ToAddress.Hex()). + Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). + Uint64("Nonce", nonce). + Int64("Gas Limit", gasLimit). + Str("Gas Price", gasPrice.String()). + Str("Gas Fee Cap", gasFeeCap.String()). + Str("Gas Tip Cap", gasTipCap.String()). + Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). + Msg("About to send funds") + + ctx, cancel = context.WithTimeout(ctx, txTimeout) + defer cancel() + err = client.Client.SendTransaction(ctx, signedTx) + if err != nil { + return nil, errors.Wrap(err, "failed to send transaction") + } + + logger.Debug(). + Str("From", fromAddress.Hex()). + Str("To", payload.ToAddress.Hex()). + Str("TxHash", signedTx.Hash().String()). + Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). + Uint64("Nonce", nonce). + Int64("Gas Limit", gasLimit). + Str("Gas Price", gasPrice.String()). + Str("Gas Fee Cap", gasFeeCap.String()). + Str("Gas Tip Cap", gasTipCap.String()). + Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). + Msg("Sent funds") + + receipt, receiptErr := client.WaitMined(ctx, logger, client.Client, signedTx) + if receiptErr != nil { + return nil, errors.Wrap(receiptErr, "failed to wait for transaction to be mined") + } + + if receipt.Status == 1 { + return receipt, nil + } + + tx, _, err := client.Client.TransactionByHash(ctx, signedTx.Hash()) + if err != nil { + return nil, errors.Wrap(err, "failed to get transaction by hash ") + } + + _, err = client.Decode(tx, receiptErr) + if err != nil { + return nil, err + } + + return receipt, nil +} + +// DeployForwarderContracts first deploys Operator Factory and then uses it to deploy given number of +// operator and forwarder pairs. It waits for each transaction to be mined and then extracts operator and +// forwarder addresses from emitted events. +func DeployForwarderContracts( + t *testing.T, + seth *seth.Client, + linkTokenAddress common.Address, + numberOfOperatorForwarderPairs int, +) (operators []common.Address, authorizedForwarders []common.Address, operatorFactoryInstance contracts.OperatorFactory) { + instance, err := contracts.DeployEthereumOperatorFactory(seth, linkTokenAddress) + require.NoError(t, err, "failed to create new instance of operator factory") + operatorFactoryInstance = &instance + + for i := 0; i < numberOfOperatorForwarderPairs; i++ { + decodedTx, err := seth.Decode(operatorFactoryInstance.DeployNewOperatorAndForwarder()) + require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") + + for i, event := range decodedTx.Events { + require.True(t, len(event.Topics) > 0, fmt.Sprintf("Event %d should have topics", i)) + switch event.Topics[0] { + case operator_factory.OperatorFactoryOperatorCreated{}.Topic().String(): + if address, ok := event.EventData["operator"]; ok { + operators = append(operators, address.(common.Address)) + } else { + require.Fail(t, "Operator address not found in event", event) + } + case operator_factory.OperatorFactoryAuthorizedForwarderCreated{}.Topic().String(): + if address, ok := event.EventData["forwarder"]; ok { + authorizedForwarders = append(authorizedForwarders, address.(common.Address)) + } else { + require.Fail(t, "Forwarder address not found in event", event) + } + } + } + } + return operators, authorizedForwarders, operatorFactoryInstance +} + +// WatchNewOCRRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new +// round from the contract, as this can cause some odd behavior in some cases. It announces success if latest round +// is >= roundNumber. +func WatchNewOCRRound( + l zerolog.Logger, + seth *seth.Client, + roundNumber int64, + ocrInstances []contracts.OffChainAggregatorWithRounds, + timeout time.Duration, +) error { + confirmed := make(map[string]bool) + timeoutC := time.After(timeout) + ticker := time.NewTicker(time.Millisecond * 200) + defer ticker.Stop() + + l.Info().Msgf("Waiting for round %d to be confirmed by all nodes", roundNumber) + + for { + select { + case <-timeoutC: + return fmt.Errorf("timeout waiting for round %d to be confirmed. %d/%d nodes confirmed it", roundNumber, len(confirmed), len(ocrInstances)) + case <-ticker.C: + for i := 0; i < len(ocrInstances); i++ { + if confirmed[ocrInstances[i].Address()] { + continue + } + ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) + roundData, err := ocrInstances[i].GetLatestRound(ctx) + if err != nil { + cancel() + return fmt.Errorf("getting latest round from OCR instance %d have failed: %w", i+1, err) + } + cancel() + if roundData.RoundId.Cmp(big.NewInt(roundNumber)) >= 0 { + l.Debug().Msgf("OCR instance %d/%d confirmed round %d", i+1, len(ocrInstances), roundNumber) + confirmed[ocrInstances[i].Address()] = true + } + } + if len(confirmed) == len(ocrInstances) { + return nil + } + } + } +} + +// AcceptAuthorizedReceiversOperator sets authorized receivers for each operator contract to +// authorizedForwarder and authorized EA to nodeAddresses. Once done, it confirms that authorizations +// were set correctly. +func AcceptAuthorizedReceiversOperator( + t *testing.T, + logger zerolog.Logger, + seth *seth.Client, + operator common.Address, + authorizedForwarder common.Address, + nodeAddresses []common.Address, +) { + operatorInstance, err := contracts.LoadEthereumOperator(logger, seth, operator) + require.NoError(t, err, "Loading operator contract shouldn't fail") + forwarderInstance, err := contracts.LoadEthereumAuthorizedForwarder(seth, authorizedForwarder) + require.NoError(t, err, "Loading authorized forwarder contract shouldn't fail") + + err = operatorInstance.AcceptAuthorizedReceivers([]common.Address{authorizedForwarder}, nodeAddresses) + require.NoError(t, err, "Accepting authorized forwarder shouldn't fail") + + senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t)) + require.NoError(t, err, "Getting authorized senders shouldn't fail") + var nodesAddrs []string + for _, o := range nodeAddresses { + nodesAddrs = append(nodesAddrs, o.Hex()) + } + require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses") + + owner, err := forwarderInstance.Owner(testcontext.Get(t)) + require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail") + require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator") +} + +// TrackForwarder creates forwarder track for a given Chainlink node +func TrackForwarder( + t *testing.T, + seth *seth.Client, + authorizedForwarder common.Address, + node contracts.ChainlinkNodeWithForwarder, +) { + l := logging.GetTestLogger(t) + chainID := big.NewInt(seth.ChainID) + _, _, err := node.TrackForwarder(chainID, authorizedForwarder) + require.NoError(t, err, "Forwarder track should be created") + l.Info().Str("NodeURL", node.GetConfig().URL). + Str("ForwarderAddress", authorizedForwarder.Hex()). + Str("ChaindID", chainID.String()). + Msg("Forwarder tracked") +} + +// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults +func DeployOCRv2Contracts( + l zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenAddress common.Address, + transmitters []string, + ocrOptions contracts.OffchainOptions, +) ([]contracts.OffchainAggregatorV2, error) { + var ocrInstances []contracts.OffchainAggregatorV2 + for contractCount := 0; contractCount < numberOfContracts; contractCount++ { + ocrInstance, err := contracts.DeployOffchainAggregatorV2( + l, + seth, + linkTokenAddress, + ocrOptions, + ) + if err != nil { + return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } + } + + // Gather address payees + var payees []string + for range transmitters { + payees = append(payees, seth.Addresses[0].Hex()) + } + + // Set Payees + for contractCount, ocrInstance := range ocrInstances { + err := ocrInstance.SetPayees(transmitters, payees) + if err != nil { + return nil, fmt.Errorf("error settings OCR payees: %w", err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } + } + return ocrInstances, nil +} + +// ConfigureOCRv2AggregatorContracts sets configuration for a number of OCRv2 contracts +func ConfigureOCRv2AggregatorContracts( + contractConfig *contracts.OCRv2Config, + ocrv2Contracts []contracts.OffchainAggregatorV2, +) error { + for contractCount, ocrInstance := range ocrv2Contracts { + // Exclude the first node, which will be used as a bootstrapper + err := ocrInstance.SetConfig(contractConfig) + if err != nil { + return fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } + } + return nil +} + +// TeardownSuite tears down networks/clients and environment and creates a logs folder for failed tests in the +// specified path. Can also accept a testreporter (if one was used) to log further results +func TeardownSuite( + t *testing.T, + chainClient *seth.Client, + env *environment.Environment, + chainlinkNodes []*client.ChainlinkK8sClient, + optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics + failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level + grafnaUrlProvider testreporters.GrafanaURLProvider, +) error { + l := logging.GetTestLogger(t) + if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { + return fmt.Errorf("Error dumping environment logs, leaving environment running for manual retrieval, err: %w", err) + } + // Delete all jobs to stop depleting the funds + err := DeleteAllJobs(chainlinkNodes) + if err != nil { + l.Warn().Msgf("Error deleting jobs %+v", err) + } + + if chainlinkNodes != nil { + if err := ReturnFundsFromNodes(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { + // This printed line is required for tests that use real funds to propagate the failure + // out to the system running the test. Do not remove + fmt.Println(environment.FAILED_FUND_RETURN) + l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). + Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + + "Environment is left running so you can try manually!") + } + } else { + l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") + } + + return env.Shutdown() +} + +// TeardownRemoteSuite sends a report and returns funds from chainlink nodes to network's default wallet +func TeardownRemoteSuite( + t *testing.T, + client *seth.Client, + namespace string, + chainlinkNodes []*client.ChainlinkK8sClient, + optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics + grafnaUrlProvider testreporters.GrafanaURLProvider, +) error { + l := logging.GetTestLogger(t) + if err := testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { + l.Warn().Err(err).Msg("Error writing test report") + } + // Delete all jobs to stop depleting the funds + err := DeleteAllJobs(chainlinkNodes) + if err != nil { + l.Warn().Msgf("Error deleting jobs %+v", err) + } + + if err = ReturnFundsFromNodes(l, client, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { + l.Error().Err(err).Str("Namespace", namespace). + Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + + "Environment is left running so you can try manually!") + } + + return err +} + +// DeleteAllJobs deletes all jobs from all chainlink nodes +// added here temporarily to avoid circular import +func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { + for _, node := range chainlinkNodes { + if node == nil { + return fmt.Errorf("found a nil chainlink node in the list of chainlink nodes while tearing down: %v", chainlinkNodes) + } + jobs, _, err := node.ReadJobs() + if err != nil { + return fmt.Errorf("error reading jobs from chainlink node, err: %w", err) + } + for _, maps := range jobs.Data { + if _, ok := maps["id"]; !ok { + return fmt.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data) + } + id := maps["id"].(string) + _, err := node.DeleteJob(id) + if err != nil { + return fmt.Errorf("error deleting job from chainlink node, err: %w", err) + } + } + } + return nil +} + +// StartNewRound requests a new round from the ocr contracts and returns once transaction was mined +func StartNewRound( + ocrInstances []contracts.OffChainAggregatorWithRounds, +) error { + for i := 0; i < len(ocrInstances); i++ { + err := ocrInstances[i].RequestNewRound() + if err != nil { + return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) + } + } + return nil +} + +// DeployOCRContractsForwarderFlow deploys and funds a certain number of offchain +// aggregator contracts with forwarders as effectiveTransmitters +func DeployOCRContractsForwarderFlow( + logger zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenContractAddress common.Address, + workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, + forwarderAddresses []common.Address, +) ([]contracts.OffchainAggregator, error) { + transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { + transmitters = make([]string, 0) + payees = make([]string, 0) + for _, forwarderCommonAddress := range forwarderAddresses { + forwarderAddress := forwarderCommonAddress.Hex() + transmitters = append(transmitters, forwarderAddress) + payees = append(payees, seth.Addresses[0].Hex()) + } + + return + } + + transmitterAddressesFn := func() ([]common.Address, error) { + return forwarderAddresses, nil + } -// RPCRawClient -// created separate client since method evmClient.RawJsonRPCCall fails on "invalid argument 0: json: cannot unmarshal non-string into Go value of type hexutil.Uint64" -type RPCRawClient struct { - resty *resty.Client + return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) } -func NewRPCRawClient(url string) *RPCRawClient { - isDebug := os.Getenv("DEBUG_RESTY") == "true" - restyClient := resty.New().SetDebug(isDebug).SetBaseURL(url) - return &RPCRawClient{ - resty: restyClient, +// DeployOCRv1Contracts deploys and funds a certain number of offchain aggregator contracts +func DeployOCRv1Contracts( + logger zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenContractAddress common.Address, + workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, +) ([]contracts.OffchainAggregator, error) { + transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { + transmitters = make([]string, 0) + payees = make([]string, 0) + for _, node := range workerNodes { + var addr string + addr, err = node.PrimaryEthAddress() + if err != nil { + err = fmt.Errorf("error getting node's primary ETH address: %w", err) + return + } + transmitters = append(transmitters, addr) + payees = append(payees, seth.Addresses[0].Hex()) + } + + return } + + transmitterAddressesFn := func() ([]common.Address, error) { + transmitterAddresses := make([]common.Address, 0) + for _, node := range workerNodes { + primaryAddress, err := node.PrimaryEthAddress() + if err != nil { + return nil, err + } + transmitterAddresses = append(transmitterAddresses, common.HexToAddress(primaryAddress)) + } + + return transmitterAddresses, nil + } + + return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) } -func (g *RPCRawClient) SetHeadForSimulatedChain(setHeadToBlockNumber uint64) (JsonRPCResponse, error) { - var responseObject JsonRPCResponse - postBody, _ := json.Marshal(map[string]any{ - "jsonrpc": "2.0", - "id": 1, - "method": "debug_setHead", - "params": []string{hexutil.EncodeUint64(setHeadToBlockNumber)}, - }) - resp, err := g.resty.R(). - SetHeader("Content-Type", "application/json"). - SetBody(postBody). - SetResult(&responseObject). - Post("") +func deployAnyOCRv1Contracts( + logger zerolog.Logger, + seth *seth.Client, + numberOfContracts int, + linkTokenContractAddress common.Address, + workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, + getTransmitterAndPayeesFn func() ([]string, []string, error), + getTransmitterAddressesFn func() ([]common.Address, error), +) ([]contracts.OffchainAggregator, error) { + // Deploy contracts + var ocrInstances []contracts.OffchainAggregator + for contractCount := 0; contractCount < numberOfContracts; contractCount++ { + ocrInstance, err := contracts.DeployOffchainAggregator(logger, seth, linkTokenContractAddress, contracts.DefaultOffChainAggregatorOptions()) + if err != nil { + return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) + } + ocrInstances = append(ocrInstances, &ocrInstance) + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } + } + + // Gather transmitter and address payees + var transmitters, payees []string + var err error + transmitters, payees, err = getTransmitterAndPayeesFn() + if err != nil { + return nil, fmt.Errorf("error getting transmitter and payees: %w", err) + } + + // Set Payees + for contractCount, ocrInstance := range ocrInstances { + err := ocrInstance.SetPayees(transmitters, payees) + if err != nil { + return nil, fmt.Errorf("error settings OCR payees: %w", err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } + } + // Set Config + transmitterAddresses, err := getTransmitterAddressesFn() if err != nil { - return JsonRPCResponse{}, fmt.Errorf("error making API request: %w", err) + return nil, fmt.Errorf("getting transmitter addresses should not fail: %w", err) } - statusCode := resp.StatusCode() - if statusCode != 200 && statusCode != 201 { - return JsonRPCResponse{}, fmt.Errorf("error invoking debug_setHead method, received unexpected status code %d: %s", statusCode, resp.String()) + + for contractCount, ocrInstance := range ocrInstances { + // Exclude the first node, which will be used as a bootstrapper + err = ocrInstance.SetConfig( + workerNodes, + contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), + transmitterAddresses, + ) + if err != nil { + return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) + } + if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some + time.Sleep(2 * time.Second) + } } - if responseObject.Error != "" { - return JsonRPCResponse{}, fmt.Errorf("received non-empty error field: %v", responseObject.Error) + + return ocrInstances, nil +} + +func privateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) { + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + return common.Address{}, errors.New("error casting public key to ECDSA") } - return responseObject, nil + return crypto.PubkeyToAddress(*publicKeyECDSA), nil } -type JsonRPCResponse struct { - Version string `json:"jsonrpc"` - Id int `json:"id"` - Result string `json:"result,omitempty"` - Error string `json:"error,omitempty"` +func WatchNewFluxRound( + l zerolog.Logger, + seth *seth.Client, + roundNumber int64, + fluxInstance contracts.FluxAggregator, + timeout time.Duration, +) error { + timeoutC := time.After(timeout) + ticker := time.NewTicker(time.Millisecond * 200) + defer ticker.Stop() + + l.Info().Msgf("Waiting for flux round %d to be confirmed by flux aggregator", roundNumber) + + for { + select { + case <-timeoutC: + return fmt.Errorf("timeout waiting for round %d to be confirmed", roundNumber) + case <-ticker.C: + ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) + roundId, err := fluxInstance.LatestRoundID(ctx) + if err != nil { + cancel() + return fmt.Errorf("getting latest round from flux instance has failed: %w", err) + } + cancel() + if roundId.Cmp(big.NewInt(roundNumber)) >= 0 { + l.Debug().Msgf("Flux instance confirmed round %d", roundNumber) + return nil + } + } + } +} + +// EstimateCostForChainlinkOperations estimates the cost of running a number of operations on the Chainlink node based on estimated gas costs. It supports +// both legacy and EIP-1559 transactions. +func EstimateCostForChainlinkOperations(l zerolog.Logger, client *seth.Client, network blockchain.EVMNetwork, amountOfOperations int) (*big.Float, error) { + bigAmountOfOperations := big.NewInt(int64(amountOfOperations)) + estimations := client.CalculateGasEstimations(client.NewDefaultGasEstimationRequest()) + + gasLimit := network.GasEstimationBuffer + network.ChainlinkTransactionLimit + + var gasPriceInWei *big.Int + if client.Cfg.Network.EIP1559DynamicFees { + gasPriceInWei = estimations.GasFeeCap + } else { + gasPriceInWei = estimations.GasPrice + } + + gasCostPerOperationWei := big.NewInt(1).Mul(big.NewInt(1).SetUint64(gasLimit), gasPriceInWei) + gasCostPerOperationETH := conversions.WeiToEther(gasCostPerOperationWei) + // total Wei needed for all TXs = total value for TX * number of TXs + totalWeiForAllOperations := big.NewInt(1).Mul(gasCostPerOperationWei, bigAmountOfOperations) + totalEthForAllOperations := conversions.WeiToEther(totalWeiForAllOperations) + + l.Debug(). + Int("Number of Operations", amountOfOperations). + Uint64("Gas Limit per Operation", gasLimit). + Str("Value per Operation (ETH)", gasCostPerOperationETH.String()). + Str("Total (ETH)", totalEthForAllOperations.String()). + Msg("Calculated ETH for Chainlink Operations") + + return totalEthForAllOperations, nil +} + +// GetLatestFinalizedBlockHeader returns latest finalised block header for given network (taking into account finality tag/depth) +func GetLatestFinalizedBlockHeader(ctx context.Context, client *seth.Client, network blockchain.EVMNetwork) (*types.Header, error) { + if network.FinalityTag { + return client.Client.HeaderByNumber(ctx, big.NewInt(rpc.FinalizedBlockNumber.Int64())) + } + if network.FinalityDepth == 0 { + return nil, fmt.Errorf("finality depth is 0 and finality tag is not enabled") + } + header, err := client.Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, err + } + latestBlockNumber := header.Number.Uint64() + finalizedBlockNumber := latestBlockNumber - network.FinalityDepth + return client.Client.HeaderByNumber(ctx, big.NewInt(int64(finalizedBlockNumber))) +} + +// SendLinkFundsToDeploymentAddresses sends LINK token to all addresses, but the root one, from the root address. It uses +// Multicall contract to batch all transfers in a single transaction. It also checks if the funds were transferred correctly. +// It's primary use case is to fund addresses that will be used for Upkeep registration (as that requires LINK balance) during +// Automation/Keeper test setup. +func SendLinkFundsToDeploymentAddresses( + chainClient *seth.Client, + concurrency, + totalUpkeeps, + operationsPerAddress int, + multicallAddress common.Address, + linkAmountPerUpkeep *big.Int, + linkToken contracts.LinkToken, +) error { + var generateCallData = func(receiver common.Address, amount *big.Int) ([]byte, error) { + abi, err := link_token_interface.LinkTokenMetaData.GetAbi() + if err != nil { + return nil, err + } + data, err := abi.Pack("transfer", receiver, amount) + if err != nil { + return nil, err + } + return data, nil + } + + toTransferToMultiCallContract := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(totalUpkeeps+concurrency))) + toTransferPerClient := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(operationsPerAddress+1))) + err := linkToken.Transfer(multicallAddress.Hex(), toTransferToMultiCallContract) + if err != nil { + return errors.Wrapf(err, "Error transferring LINK to multicall contract") + } + + balance, err := linkToken.BalanceOf(context.Background(), multicallAddress.Hex()) + if err != nil { + return errors.Wrapf(err, "Error getting LINK balance of multicall contract") + } + + if balance.Cmp(toTransferToMultiCallContract) < 0 { + return fmt.Errorf("Incorrect LINK balance of multicall contract. Expected at least: %s. Got: %s", toTransferToMultiCallContract.String(), balance.String()) + } + + // Transfer LINK to ephemeral keys + multiCallData := make([][]byte, 0) + for i := 1; i <= concurrency; i++ { + data, err := generateCallData(chainClient.Addresses[i], toTransferPerClient) + if err != nil { + return errors.Wrapf(err, "Error generating call data for LINK transfer") + } + multiCallData = append(multiCallData, data) + } + + var call []contracts.Call + for _, d := range multiCallData { + data := contracts.Call{Target: common.HexToAddress(linkToken.Address()), AllowFailure: false, CallData: d} + call = append(call, data) + } + + multiCallABI, err := abi.JSON(strings.NewReader(contracts.MultiCallABI)) + if err != nil { + return errors.Wrapf(err, "Error getting Multicall contract ABI") + } + boundContract := bind.NewBoundContract(multicallAddress, multiCallABI, chainClient.Client, chainClient.Client, chainClient.Client) + // call aggregate3 to group all msg call data and send them in a single transaction + _, err = chainClient.Decode(boundContract.Transact(chainClient.NewTXOpts(), "aggregate3", call)) + if err != nil { + return errors.Wrapf(err, "Error calling Multicall contract") + } + + for i := 1; i <= concurrency; i++ { + balance, err := linkToken.BalanceOf(context.Background(), chainClient.Addresses[i].Hex()) + if err != nil { + return errors.Wrapf(err, "Error getting LINK balance of ephemeral key %d", i) + } + if balance.Cmp(toTransferPerClient) < 0 { + return fmt.Errorf("Incorrect LINK balance after transfer. Ephemeral key %d. Expected: %s. Got: %s", i, toTransferPerClient.String(), balance.String()) + } + } + + return nil +} + +// GenerateUpkeepReport generates a report of performed, successful, reverted and stale upkeeps for a given registry contract based on transaction logs. In case of test failure it can help us +// to triage the issue by providing more context. +func GenerateUpkeepReport(t *testing.T, chainClient *seth.Client, startBlock, endBlock *big.Int, instance contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) (performedUpkeeps, successfulUpkeeps, revertedUpkeeps, staleUpkeeps int, err error) { + registryLogs := []gethtypes.Log{} + l := logging.GetTestLogger(t) + + var ( + blockBatchSize int64 = 100 + logs []gethtypes.Log + timeout = 5 * time.Second + addr = common.HexToAddress(instance.Address()) + queryStartBlock = startBlock + ) + + // Gather logs from the registry in 100 block chunks to avoid read limits + for queryStartBlock.Cmp(endBlock) < 0 { + filterQuery := geth.FilterQuery{ + Addresses: []common.Address{addr}, + FromBlock: queryStartBlock, + ToBlock: big.NewInt(0).Add(queryStartBlock, big.NewInt(blockBatchSize)), + } + + // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats. + err = fmt.Errorf("initial error") // to ensure our for loop runs at least once + for err != nil { + ctx, cancel := context.WithTimeout(testcontext.Get(t), timeout) + logs, err = chainClient.Client.FilterLogs(ctx, filterQuery) + cancel() + if err != nil { + l.Error(). + Err(err). + Interface("Filter Query", filterQuery). + Str("Timeout", timeout.String()). + Msg("Error getting logs from chain, trying again") + timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute))) + continue + } + l.Info(). + Uint64("From Block", queryStartBlock.Uint64()). + Uint64("To Block", filterQuery.ToBlock.Uint64()). + Int("Log Count", len(logs)). + Str("Registry Address", addr.Hex()). + Msg("Collected logs") + queryStartBlock.Add(queryStartBlock, big.NewInt(blockBatchSize)) + registryLogs = append(registryLogs, logs...) + } + } + + var contractABI *abi.ABI + contractABI, err = contracts.GetRegistryContractABI(registryVersion) + if err != nil { + return + } + + for _, allLogs := range registryLogs { + log := allLogs + var eventDetails *abi.Event + eventDetails, err = contractABI.EventByID(log.Topics[0]) + if err != nil { + l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error getting event details for log, report data inaccurate") + break + } + if eventDetails.Name == "UpkeepPerformed" { + performedUpkeeps++ + var parsedLog *contracts.UpkeepPerformedLog + parsedLog, err = instance.ParseUpkeepPerformedLog(&log) + if err != nil { + l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error parsing upkeep performed log, report data inaccurate") + break + } + if !parsedLog.Success { + revertedUpkeeps++ + } else { + successfulUpkeeps++ + } + } else if eventDetails.Name == "StaleUpkeepReport" { + staleUpkeeps++ + } + } + + return +} + +func GetStalenessReportCleanupFn(t *testing.T, logger zerolog.Logger, chainClient *seth.Client, startBlock uint64, registry contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) func() { + return func() { + if t.Failed() { + endBlock, err := chainClient.Client.BlockNumber(context.Background()) + require.NoError(t, err, "Failed to get end block") + + total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, big.NewInt(int64(startBlock)), big.NewInt(int64(endBlock)), registry, registryVersion) + require.NoError(t, err, "Failed to get staleness data") + if stale > 0 || reverted > 0 { + logger.Warn().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") + } else { + logger.Info().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") + } + } + } } diff --git a/integration-tests/actions/actions_local.go b/integration-tests/actions/actions_local.go deleted file mode 100644 index 5bb0c202a5..0000000000 --- a/integration-tests/actions/actions_local.go +++ /dev/null @@ -1,18 +0,0 @@ -// Package actions enables common chainlink interactions -package actions - -import "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" - -// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment -// to apply the upgrades -func UpgradeChainlinkNodeVersionsLocal( - newImage, newVersion string, - nodes ...*test_env.ClNode, -) error { - for _, node := range nodes { - if err := node.UpgradeVersion(newImage, newVersion); err != nil { - return err - } - } - return nil -} diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index 9ee14d4a6a..22220af9d6 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -9,6 +9,9 @@ import ( "testing" "time" + "github.com/pkg/errors" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" "github.com/lib/pq" "github.com/stretchr/testify/require" @@ -20,7 +23,6 @@ import ( ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -259,37 +261,44 @@ func CreateOCRKeeperJobs( // DeployAutoOCRRegistryAndRegistrar registry and registrar func DeployAutoOCRRegistryAndRegistrar( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, registrySettings contracts.KeeperRegistrySettings, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, ) (contracts.KeeperRegistry, contracts.KeeperRegistrar) { - registry := deployRegistry(t, registryVersion, registrySettings, contractDeployer, client, linkToken) - registrar := deployRegistrar(t, registryVersion, registry, linkToken, contractDeployer, client) + registry := deployRegistry(t, client, registryVersion, registrySettings, linkToken) + registrar := deployRegistrar(t, client, registryVersion, registry, linkToken) return registry, registrar } -func DeployConsumers(t *testing.T, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { - upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, isLogTrigger, isMercury) +// DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. +func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + + upkeeps := DeployKeeperConsumers(t, chainClient, numberOfUpkeeps, isLogTrigger, isMercury) + require.Equal(t, numberOfUpkeeps, len(upkeeps), "Number of upkeeps should match") var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } upkeepIds := RegisterUpkeepContracts( - t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, + t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, ) + require.Equal(t, numberOfUpkeeps, len(upkeepIds), "Number of upkeepIds should match") return upkeeps, upkeepIds } +// DeployPerformanceConsumers deploys and registers keeper performance consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkeep will be registered with root key address as the admin. +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. func DeployPerformanceConsumers( t *testing.T, + chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, @@ -299,44 +308,74 @@ func DeployPerformanceConsumers( performGasToBurn int64, // How much gas should be burned on performUpkeep() calls ) ([]contracts.KeeperConsumerPerformance, []*big.Int) { upkeeps := DeployKeeperConsumersPerformance( - t, contractDeployer, client, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, + t, chainClient, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, ) + + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) return upkeeps, upkeepIds } +// DeployPerformDataCheckerConsumers deploys and registers keeper performance data checkers consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. +// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deployes multicall contract and sends link funds to each deployment address. func DeployPerformDataCheckerConsumers( t *testing.T, + chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, expectedData []byte, ) ([]contracts.KeeperPerformDataChecker, []*big.Int) { - upkeeps := DeployPerformDataChecker(t, contractDeployer, client, numberOfUpkeeps, expectedData) + upkeeps := DeployPerformDataChecker(t, chainClient, numberOfUpkeeps, expectedData) + + err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) return upkeeps, upkeepIds } +// DeployMultiCallAndFundDeploymentAddresses deploys multicall contract and sends link funds to each deployment address +func DeployMultiCallAndFundDeploymentAddresses( + chainClient *seth.Client, + linkToken contracts.LinkToken, + numberOfUpkeeps int, + linkFundsForEachUpkeep *big.Int, +) error { + concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) + if err != nil { + return err + } + + operationsPerAddress := numberOfUpkeeps / concurrency + + multicallAddress, err := contracts.DeployMultiCallContract(chainClient) + if err != nil { + return errors.Wrap(err, "Error deploying multicall contract") + } + + return SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) +} + func deployRegistrar( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, registry contracts.KeeperRegistry, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, ) contracts.KeeperRegistrar { registrarSettings := contracts.KeeperRegistrarSettings{ AutoApproveConfigType: 2, @@ -344,31 +383,29 @@ func deployRegistrar( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar, err := contractDeployer.DeployKeeperRegistrar(registryVersion, linkToken.Address(), registrarSettings) + registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) require.NoError(t, err, "Deploying KeeperRegistrar contract shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for registrar to deploy") return registrar } func deployRegistry( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, registrySettings contracts.KeeperRegistrySettings, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, linkToken contracts.LinkToken, ) contracts.KeeperRegistry { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") // Deploy the transcoder here, and then set it to the registry - transcoder := DeployUpkeepTranscoder(t, contractDeployer, client) - registry := DeployKeeperRegistry(t, contractDeployer, client, + transcoder, err := contracts.DeployUpkeepTranscoder(client) + require.NoError(t, err, "Deploying upkeep transcoder shouldn't fail") + + registry, err := contracts.DeployKeeperRegistry( + client, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -379,5 +416,6 @@ func deployRegistry( Settings: registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry contract shouldn't fail") return registry } diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 25e6a4a7a0..1ed4bef141 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -25,10 +25,12 @@ import ( "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" @@ -61,6 +63,8 @@ type AutomationTest struct { LinkToken contracts.LinkToken Transcoder contracts.UpkeepTranscoder EthLinkFeed contracts.MockETHLINKFeed + EthUSDFeed contracts.MockETHUSDFeed + WETHToken contracts.WETHToken GasFeed contracts.MockGasFeed Registry contracts.KeeperRegistry Registrar contracts.KeeperRegistrar @@ -213,6 +217,43 @@ func (a *AutomationTest) LoadEthLinkFeed(address string) error { return nil } +func (a *AutomationTest) DeployEthUSDFeed() error { + // FallbackLinkPrice and FallbackETHPrice are the same + ethUSDFeed, err := contracts.DeployMockETHUSDFeed(a.ChainClient, a.RegistrySettings.FallbackLinkPrice) + if err != nil { + return err + } + a.EthUSDFeed = ethUSDFeed + return nil +} + +func (a *AutomationTest) LoadEthUSDFeed(address string) error { + ethUSDFeed, err := contracts.LoadMockETHUSDFeed(a.ChainClient, common.HexToAddress(address)) + if err != nil { + return err + } + a.EthUSDFeed = ethUSDFeed + return nil +} + +func (a *AutomationTest) DeployWETH() error { + wethToken, err := contracts.DeployWETHTokenContract(a.Logger, a.ChainClient) + if err != nil { + return err + } + a.WETHToken = wethToken + return nil +} + +func (a *AutomationTest) LoadWETH(address string) error { + wethToken, err := contracts.LoadWETHTokenContract(a.Logger, a.ChainClient, common.HexToAddress(address)) + if err != nil { + return err + } + a.WETHToken = wethToken + return nil +} + func (a *AutomationTest) DeployGasFeed() error { gasFeed, err := contracts.DeployMockGASFeed(a.ChainClient, a.RegistrySettings.FallbackGasPrice) if err != nil { @@ -233,13 +274,16 @@ func (a *AutomationTest) LoadEthGasFeed(address string) error { func (a *AutomationTest) DeployRegistry() error { registryOpts := &contracts.KeeperRegistryOpts{ - RegistryVersion: a.RegistrySettings.RegistryVersion, - LinkAddr: a.LinkToken.Address(), - ETHFeedAddr: a.EthLinkFeed.Address(), - GasFeedAddr: a.GasFeed.Address(), - TranscoderAddr: a.Transcoder.Address(), - RegistrarAddr: utils.ZeroAddress.Hex(), - Settings: a.RegistrySettings, + RegistryVersion: a.RegistrySettings.RegistryVersion, + LinkAddr: a.LinkToken.Address(), + ETHFeedAddr: a.EthLinkFeed.Address(), + GasFeedAddr: a.GasFeed.Address(), + TranscoderAddr: a.Transcoder.Address(), + RegistrarAddr: utils.ZeroAddress.Hex(), + Settings: a.RegistrySettings, + LinkUSDFeedAddr: a.EthUSDFeed.Address(), + NativeUSDFeedAddr: a.EthUSDFeed.Address(), + WrappedNativeAddr: a.WETHToken.Address(), } registry, err := contracts.DeployKeeperRegistry(a.ChainClient, registryOpts) if err != nil { @@ -263,6 +307,7 @@ func (a *AutomationTest) DeployRegistrar() error { return fmt.Errorf("registry must be deployed or loaded before registrar") } a.RegistrarSettings.RegistryAddr = a.Registry.Address() + a.RegistrarSettings.WETHTokenAddr = a.WETHToken.Address() registrar, err := contracts.DeployKeeperRegistrar(a.ChainClient, a.RegistrySettings.RegistryVersion, a.LinkToken.Address(), a.RegistrarSettings) if err != nil { return err @@ -361,14 +406,14 @@ func (a *AutomationTest) AddBootstrapJob() error { func (a *AutomationTest) AddAutomationJobs() error { var contractVersion string - if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_2 { + if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_2 || a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_3 { contractVersion = "v2.1+" } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_1 { contractVersion = "v2.1" } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_0 { contractVersion = "v2.0" } else { - return fmt.Errorf("v2.0, v2.1, and v2.2 are the only supported versions") + return fmt.Errorf("v2.0, v2.1, v2.2 and v2.3 are the only supported versions") } pluginCfg := map[string]interface{}{ "contractVersion": "\"" + contractVersion + "\"", @@ -473,13 +518,13 @@ func (a *AutomationTest) SetConfigOnRegistry() error { if err != nil { return errors.Join(err, fmt.Errorf("failed to build config args")) } - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: + case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2, ethereum.RegistryVersion_2_3: signerOnchainPublicKeys, transmitterAccounts, f, _, offchainConfigVersion, offchainConfig, err = calculateOCR3ConfigArgs(a, S, oracleIdentities) if err != nil { return errors.Join(err, fmt.Errorf("failed to build config args")) } default: - return fmt.Errorf("v2.0, v2.1, and v2.2 are the only supported versions") + return fmt.Errorf("v2.0, v2.1, v2.2 and v2.3 are the only supported versions") } var signers []common.Address @@ -517,6 +562,22 @@ func (a *AutomationTest) SetConfigOnRegistry() error { ocrConfig.TypedOnchainConfig21 = a.RegistrySettings.Create21OnchainConfig(a.Registrar.Address(), a.UpkeepPrivilegeManager) } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_2 { ocrConfig.TypedOnchainConfig22 = a.RegistrySettings.Create22OnchainConfig(a.Registrar.Address(), a.UpkeepPrivilegeManager, a.Registry.ChainModuleAddress(), a.Registry.ReorgProtectionEnabled()) + } else if a.RegistrySettings.RegistryVersion == ethereum.RegistryVersion_2_3 { + ocrConfig.TypedOnchainConfig23 = a.RegistrySettings.Create23OnchainConfig(a.Registrar.Address(), a.UpkeepPrivilegeManager, a.Registry.ChainModuleAddress(), a.Registry.ReorgProtectionEnabled()) + ocrConfig.BillingTokens = []common.Address{ + common.HexToAddress(a.LinkToken.Address()), // TODO add more billing tokens + } + + ocrConfig.BillingConfigs = []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig{ + { + GasFeePPB: 100, + FlatFeeMilliCents: big.NewInt(500), + PriceFeed: common.HexToAddress(a.EthUSDFeed.Address()), // ETH/USD feed and LINK/USD feed are the same + Decimals: 18, + FallbackPrice: big.NewInt(1000), + MinSpend: big.NewInt(200), + }, + } } err = a.Registry.SetConfigTypeSafe(ocrConfig) if err != nil { @@ -590,7 +651,7 @@ func (r registrationResult) GetResult() common.Hash { } func (a *AutomationTest) RegisterUpkeeps(upkeepConfigs []UpkeepConfig, maxConcurrency int) ([]common.Hash, error) { - concurrency, err := actions_seth.GetAndAssertCorrectConcurrency(a.ChainClient, 1) + concurrency, err := actions.GetAndAssertCorrectConcurrency(a.ChainClient, 1) if err != nil { return nil, err } @@ -691,7 +752,7 @@ func (c confirmationResult) GetResult() UpkeepId { } func (a *AutomationTest) ConfirmUpkeepsRegistered(registrationTxHashes []common.Hash, maxConcurrency int) ([]*big.Int, error) { - concurrency, err := actions_seth.GetAndAssertCorrectConcurrency(a.ChainClient, 1) + concurrency, err := actions.GetAndAssertCorrectConcurrency(a.ChainClient, 1) if err != nil { return nil, err } @@ -790,11 +851,17 @@ func (a *AutomationTest) SetupAutomationDeployment(t *testing.T) { err = a.DeployLINK() require.NoError(t, err, "Error deploying link token contract") + err = a.DeployWETH() + require.NoError(t, err, "Error deploying weth token contract") + err = a.DeployEthLinkFeed() require.NoError(t, err, "Error deploying eth link feed contract") err = a.DeployGasFeed() require.NoError(t, err, "Error deploying gas feed contract") + err = a.DeployEthUSDFeed() + require.NoError(t, err, "Error deploying eth usd feed contract") + err = a.DeployTranscoder() require.NoError(t, err, "Error deploying transcoder contract") diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 950d14ac8e..7f02f54c75 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -1,62 +1,30 @@ package actions import ( + "context" "fmt" "math" "math/big" "strconv" "testing" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/google/uuid" + "github.com/pkg/errors" + "github.com/smartcontractkit/seth" + + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" + "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) var ZeroAddress = common.Address{} -func CreateKeeperJobs( - t *testing.T, - chainlinkNodes []*client.ChainlinkK8sClient, - keeperRegistry contracts.KeeperRegistry, - ocrConfig contracts.OCRv2Config, - evmChainID string, -) { - // Send keeper jobs to registry and chainlink nodes - primaryNode := chainlinkNodes[0] - primaryNodeAddress, err := primaryNode.PrimaryEthAddress() - require.NoError(t, err, "Reading ETH Keys from Chainlink Client shouldn't fail") - nodeAddresses, err := ChainlinkNodeAddresses(chainlinkNodes) - require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - nodeAddressesStr, payees := make([]string, 0), make([]string, 0) - for _, cla := range nodeAddresses { - nodeAddressesStr = append(nodeAddressesStr, cla.Hex()) - payees = append(payees, primaryNodeAddress) - } - err = keeperRegistry.SetKeepers(nodeAddressesStr, payees, ocrConfig) - require.NoError(t, err, "Setting keepers in the registry shouldn't fail") - - for _, chainlinkNode := range chainlinkNodes { - chainlinkNodeAddress, err := chainlinkNode.PrimaryEthAddress() - require.NoError(t, err, "Error retrieving chainlink node address") - _, err = chainlinkNode.MustCreateJob(&client.KeeperJobSpec{ - Name: fmt.Sprintf("keeper-test-%s", keeperRegistry.Address()), - ContractAddress: keeperRegistry.Address(), - FromAddress: chainlinkNodeAddress, - EVMChainID: evmChainID, - MinIncomingConfirmations: 1, - }) - require.NoError(t, err, "Creating KeeperV2 Job shouldn't fail") - } -} - func CreateKeeperJobsWithKeyIndex( t *testing.T, chainlinkNodes []*client.ChainlinkK8sClient, @@ -109,20 +77,20 @@ func DeployKeeperContracts( numberOfUpkeeps int, upkeepGasLimit uint32, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, linkFundsForEachUpkeep *big.Int, ) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumer, []*big.Int) { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") // Deploy the transcoder here, and then set it to the registry - transcoder := DeployUpkeepTranscoder(t, contractDeployer, client) - registry := DeployKeeperRegistry(t, contractDeployer, client, + transcoder, err := contracts.DeployUpkeepTranscoder(client) + require.NoError(t, err, "Deploying UpkeepTranscoder contract shouldn't fail") + + registry, err := contracts.DeployKeeperRegistry( + client, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -133,6 +101,7 @@ func DeployKeeperContracts( Settings: registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) @@ -144,16 +113,9 @@ func DeployKeeperContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) - upkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfUpkeeps, false, false) - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) - err = client.WaitForEvents() - require.NoError(t, err, "Error waiting for events") + registrar := DeployKeeperRegistrar(t, client, registryVersion, linkToken, registrarSettings, registry) + upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false) return registry, registrar, upkeeps, upkeepIds } @@ -161,12 +123,11 @@ func DeployKeeperContracts( // DeployPerformanceKeeperContracts deploys a set amount of keeper performance contracts registered to a single registry func DeployPerformanceKeeperContracts( t *testing.T, + chainClient *seth.Client, registryVersion ethereum.KeeperRegistryVersion, numberOfContracts int, upkeepGasLimit uint32, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, registrySettings *contracts.KeeperRegistrySettings, linkFundsForEachUpkeep *big.Int, blockRange, // How many blocks to run the test for @@ -174,14 +135,13 @@ func DeployPerformanceKeeperContracts( checkGasToBurn, // How much gas should be burned on checkUpkeep() calls performGasToBurn int64, // How much gas should be burned on performUpkeep() calls ) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumerPerformance, []*big.Int) { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") - registry := DeployKeeperRegistry(t, contractDeployer, client, + registry, err := contracts.DeployKeeperRegistry( + chainClient, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -192,6 +152,7 @@ func DeployPerformanceKeeperContracts( Settings: *registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) @@ -203,10 +164,13 @@ func DeployPerformanceKeeperContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) + registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) + + err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") upkeeps := DeployKeeperConsumersPerformance( - t, contractDeployer, client, numberOfContracts, blockRange, blockInterval, checkGasToBurn, performGasToBurn, + t, chainClient, numberOfContracts, blockRange, blockInterval, checkGasToBurn, performGasToBurn, ) var upkeepsAddresses []string @@ -214,7 +178,7 @@ func DeployPerformanceKeeperContracts( upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) return registry, registrar, upkeeps, upkeepIds } @@ -222,24 +186,22 @@ func DeployPerformanceKeeperContracts( // DeployPerformDataCheckerContracts deploys a set amount of keeper perform data checker contracts registered to a single registry func DeployPerformDataCheckerContracts( t *testing.T, + chainClient *seth.Client, registryVersion ethereum.KeeperRegistryVersion, numberOfContracts int, upkeepGasLimit uint32, linkToken contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, registrySettings *contracts.KeeperRegistrySettings, linkFundsForEachUpkeep *big.Int, expectedData []byte, ) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperPerformDataChecker, []*big.Int) { - ef, err := contractDeployer.DeployMockETHLINKFeed(big.NewInt(2e18)) + ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contractDeployer.DeployMockGasFeed(big.NewInt(2e11)) + gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for mock feeds to deploy") - registry := DeployKeeperRegistry(t, contractDeployer, client, + registry, err := contracts.DeployKeeperRegistry( + chainClient, &contracts.KeeperRegistryOpts{ RegistryVersion: registryVersion, LinkAddr: linkToken.Address(), @@ -250,6 +212,7 @@ func DeployPerformDataCheckerContracts( Settings: *registrySettings, }, ) + require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) @@ -261,124 +224,127 @@ func DeployPerformDataCheckerContracts( RegistryAddr: registry.Address(), MinLinkJuels: big.NewInt(0), } - registrar := DeployKeeperRegistrar(t, registryVersion, linkToken, registrarSettings, contractDeployer, client, registry) - upkeeps := DeployPerformDataChecker(t, contractDeployer, client, numberOfContracts, expectedData) + registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) + upkeeps := DeployPerformDataChecker(t, chainClient, numberOfContracts, expectedData) + + err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") var upkeepsAddresses []string for _, upkeep := range upkeeps { upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) } - upkeepIds := RegisterUpkeepContracts(t, linkToken, linkFundsForEachUpkeep, client, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) + upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) return registry, registrar, upkeeps, upkeepIds } -func DeployKeeperRegistry( - t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, - registryOpts *contracts.KeeperRegistryOpts, -) contracts.KeeperRegistry { - registry, err := contractDeployer.DeployKeeperRegistry( - registryOpts, - ) - require.NoError(t, err, "Deploying keeper registry shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for keeper registry to deploy") - - return registry -} - func DeployKeeperRegistrar( t *testing.T, + client *seth.Client, registryVersion ethereum.KeeperRegistryVersion, linkToken contracts.LinkToken, registrarSettings contracts.KeeperRegistrarSettings, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, registry contracts.KeeperRegistry, ) contracts.KeeperRegistrar { - registrar, err := contractDeployer.DeployKeeperRegistrar(registryVersion, linkToken.Address(), registrarSettings) - - require.NoError(t, err, "Deploying KeeperRegistrar contract shouldn't fail") - err = client.WaitForEvents() + registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) require.NoError(t, err, "Failed waiting for registrar to deploy") if registryVersion != ethereum.RegistryVersion_2_0 { err = registry.SetRegistrar(registrar.Address()) require.NoError(t, err, "Registering the registrar address on the registry shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for registry to set registrar") } return registrar } -func DeployUpkeepTranscoder( - t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, -) contracts.UpkeepTranscoder { - transcoder, err := contractDeployer.DeployUpkeepTranscoder() - require.NoError(t, err, "Deploying UpkeepTranscoder contract shouldn't fail") - err = client.WaitForEvents() - require.NoError(t, err, "Failed waiting for transcoder to deploy") - - return transcoder -} - -func RegisterUpkeepContracts(t *testing.T, linkToken contracts.LinkToken, linkFunds *big.Int, client blockchain.EVMClient, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { +func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { checkData := make([][]byte, 0) for i := 0; i < numberOfContracts; i++ { checkData = append(checkData, []byte("0")) } return RegisterUpkeepContractsWithCheckData( - t, linkToken, linkFunds, client, upkeepGasLimit, registry, registrar, + t, client, linkToken, linkFunds, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepAddresses, checkData, isLogTrigger, isMercury) } -func RegisterUpkeepContractsWithCheckData(t *testing.T, linkToken contracts.LinkToken, linkFunds *big.Int, client blockchain.EVMClient, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { +type upkeepRegistrationResult struct { + upkeepID UpkeepId +} + +func (r upkeepRegistrationResult) GetResult() *big.Int { + return r.upkeepID +} + +type upkeepConfig struct { + address string + data []byte +} + +type UpkeepId = *big.Int + +func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { l := logging.GetTestLogger(t) - registrationTxHashes := make([]common.Hash, 0) - upkeepIds := make([]*big.Int, 0) - for contractCount, upkeepAddress := range upkeepAddresses { + + concurrency, err := GetAndAssertCorrectConcurrency(client, 1) + require.NoError(t, err, "Insufficient concurrency to execute action") + + executor := ctf_concurrency.NewConcurrentExecutor[UpkeepId, upkeepRegistrationResult, upkeepConfig](l) + + configs := make([]upkeepConfig, 0) + for i := 0; i < len(upkeepAddresses); i++ { + configs = append(configs, upkeepConfig{address: upkeepAddresses[i], data: checkData[i]}) + } + + var registerUpkeepFn = func(resultCh chan upkeepRegistrationResult, errorCh chan error, executorNum int, config upkeepConfig) { + id := uuid.New().String() + keyNum := executorNum + 1 // key 0 is the root key + req, err := registrar.EncodeRegisterRequest( - fmt.Sprintf("upkeep_%d", contractCount+1), + fmt.Sprintf("upkeep_%s", id), []byte("test@mail.com"), - upkeepAddress, + config.address, upkeepGasLimit, - client.GetDefaultWallet().Address(), // upkeep Admin - checkData[contractCount], + client.MustGetRootKeyAddress().Hex(), // upkeep Admin + config.data, linkFunds, 0, - client.GetDefaultWallet().Address(), + client.Addresses[keyNum].Hex(), isLogTrigger, isMercury, + linkToken.Address(), ) - require.NoError(t, err, "Encoding the register request shouldn't fail") - tx, err := linkToken.TransferAndCall(registrar.Address(), linkFunds, req) - require.NoError(t, err, "Error registering the upkeep consumer to the registrar") - l.Debug(). - Str("Contract Address", upkeepAddress). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Str("TxHash", tx.Hash().String()). - Str("Check Data", hexutil.Encode(checkData[contractCount])). - Msg("Registered Keeper Consumer Contract") - registrationTxHashes = append(registrationTxHashes, tx.Hash()) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait after registering upkeep consumers") + + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to encode register request for upkeep at %s", id, config.address) + return + } + + balance, err := linkToken.BalanceOf(context.Background(), client.Addresses[keyNum].Hex()) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s]Failed to get LINK balance of %s", id, client.Addresses[keyNum].Hex()) + return + } + + // not stricly necessary, but helps us to avoid an errorless revert if there is not enough LINK + if balance.Cmp(linkFunds) < 0 { + errorCh <- fmt.Errorf("[id: %s] Not enough LINK balance for %s. Has: %s. Needs: %s", id, client.Addresses[keyNum].Hex(), balance.String(), linkFunds.String()) + return + } + + tx, err := linkToken.TransferAndCallFromKey(registrar.Address(), linkFunds, req, keyNum) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to register upkeep at %s", id, config.address) + return + } + + receipt, err := client.Client.TransactionReceipt(context.Background(), tx.Hash()) + if err != nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed to get receipt for upkeep at %s and tx hash %s", id, config.address, tx.Hash()) + return } - } - err := client.WaitForEvents() - require.NoError(t, err, "Failed while waiting for all consumer contracts to be registered to registrar") - // Fetch the upkeep IDs - for _, txHash := range registrationTxHashes { - receipt, err := client.GetTxReceipt(txHash) - require.NoError(t, err, "Registration tx should be completed") var upkeepId *big.Int for _, rawLog := range receipt.Logs { parsedUpkeepId, err := registry.ParseUpkeepIdFromRegisteredLog(rawLog) @@ -387,63 +353,87 @@ func RegisterUpkeepContractsWithCheckData(t *testing.T, linkToken contracts.Link break } } - require.NotNil(t, upkeepId, "Upkeep ID should be found after registration") + + if upkeepId == nil { + errorCh <- errors.Wrapf(err, "[id: %s] Failed find upkeep ID for upkeep at %s in logs of tx with hash %s", id, config.address, tx.Hash()) + return + } + l.Debug(). - Str("TxHash", txHash.String()). + Str("TxHash", tx.Hash().String()). Str("Upkeep ID", upkeepId.String()). Msg("Found upkeepId in tx hash") - upkeepIds = append(upkeepIds, upkeepId) + + resultCh <- upkeepRegistrationResult{upkeepID: upkeepId} } + + upkeepIds, err := executor.Execute(concurrency, configs, registerUpkeepFn) + require.NoError(t, err, "Failed to register upkeeps using executor") + + require.Equal(t, numberOfContracts, len(upkeepIds), "Incorrect number of Keeper Consumer Contracts registered") l.Info().Msg("Successfully registered all Keeper Consumer Contracts") + return upkeepIds } -func DeployKeeperConsumers(t *testing.T, contractDeployer contracts.ContractDeployer, client blockchain.EVMClient, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { +type keeperConsumerResult struct { + contract contracts.KeeperConsumer +} + +func (k keeperConsumerResult) GetResult() contracts.KeeperConsumer { + return k.contract +} + +// DeployKeeperConsumers concurrently deploys keeper consumer contracts. It requires at least 1 ephemeral key to be present in Seth config. +func DeployKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { l := logging.GetTestLogger(t) - keeperConsumerContracts := make([]contracts.KeeperConsumer, 0) - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer + concurrency, err := GetAndAssertCorrectConcurrency(client, 1) + require.NoError(t, err, "Insufficient concurrency to execute action") + + executor := ctf_concurrency.NewConcurrentExecutor[contracts.KeeperConsumer, keeperConsumerResult, ctf_concurrency.NoTaskType](l) + + var deployContractFn = func(channel chan keeperConsumerResult, errorCh chan error, executorNum int) { + keyNum := executorNum + 1 // key 0 is the root key var keeperConsumerInstance contracts.KeeperConsumer var err error if isMercury && isLogTrigger { // v2.1 only: Log triggered based contract with Mercury enabled - keeperConsumerInstance, err = contractDeployer.DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() + keeperConsumerInstance, err = contracts.DeployAutomationLogTriggeredStreamsLookupUpkeepConsumerFromKey(client, keyNum) } else if isMercury { // v2.1 only: Conditional based contract with Mercury enabled - keeperConsumerInstance, err = contractDeployer.DeployAutomationStreamsLookupUpkeepConsumer(big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range + keeperConsumerInstance, err = contracts.DeployAutomationStreamsLookupUpkeepConsumerFromKey(client, keyNum, big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range } else if isLogTrigger { // v2.1 only: Log triggered based contract without Mercury - keeperConsumerInstance, err = contractDeployer.DeployAutomationLogTriggerConsumer(big.NewInt(1000)) // 1000 block test range + keeperConsumerInstance, err = contracts.DeployAutomationLogTriggerConsumerFromKey(client, keyNum, big.NewInt(1000)) // 1000 block test range } else { // v2.0 and v2.1: Conditional based contract without Mercury - keeperConsumerInstance, err = contractDeployer.DeployUpkeepCounter(big.NewInt(999999), big.NewInt(5)) + keeperConsumerInstance, err = contracts.DeployUpkeepCounterFromKey(client, keyNum, big.NewInt(999999), big.NewInt(5)) } - require.NoError(t, err, "Deploying Consumer instance %d shouldn't fail", contractCount+1) - keeperConsumerContracts = append(keeperConsumerContracts, keeperConsumerInstance) - l.Debug(). - Str("Contract Address", keeperConsumerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Consumer Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err := client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumer deployments") + if err != nil { + errorCh <- errors.Wrapf(err, "Failed to deploy keeper consumer contract") + return } + + channel <- keeperConsumerResult{contract: keeperConsumerInstance} } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + + results, err := executor.ExecuteSimple(concurrency, numberOfContracts, deployContractFn) + require.NoError(t, err, "Failed to deploy keeper consumers") + + // require.Equal(t, 0, len(deplymentErrors), "Error deploying consumer contracts") + require.Equal(t, numberOfContracts, len(results), "Incorrect number of Keeper Consumer Contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - return keeperConsumerContracts + return results } +// DeployKeeperConsumersPerformance sequentially deploys keeper performance consumer contracts. func DeployKeeperConsumersPerformance( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, blockRange, // How many blocks to run the test for blockInterval, // Interval of blocks that upkeeps are expected to be performed @@ -455,7 +445,8 @@ func DeployKeeperConsumersPerformance( for contractCount := 0; contractCount < numberOfContracts; contractCount++ { // Deploy consumer - keeperConsumerInstance, err := contractDeployer.DeployKeeperConsumerPerformance( + keeperConsumerInstance, err := contracts.DeployKeeperConsumerPerformance( + client, big.NewInt(blockRange), big.NewInt(blockInterval), big.NewInt(checkGasToBurn), @@ -468,22 +459,18 @@ func DeployKeeperConsumersPerformance( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed Keeper Performance Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumerPerformance deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + + require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of consumers contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return upkeeps } +// DeployPerformDataChecker sequentially deploys keeper perform data checker contracts. func DeployPerformDataChecker( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, expectedData []byte, ) []contracts.KeeperPerformDataChecker { @@ -491,7 +478,7 @@ func DeployPerformDataChecker( upkeeps := make([]contracts.KeeperPerformDataChecker, 0) for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - performDataCheckerInstance, err := contractDeployer.DeployKeeperPerformDataChecker(expectedData) + performDataCheckerInstance, err := contracts.DeployKeeperPerformDataChecker(client, expectedData) require.NoError(t, err, "Deploying KeeperPerformDataChecker instance %d shouldn't fail", contractCount+1) upkeeps = append(upkeeps, performDataCheckerInstance) l.Debug(). @@ -499,22 +486,17 @@ func DeployPerformDataChecker( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed PerformDataChecker Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for PerformDataChecker deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper perform data checker contracts") + require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of PerformDataChecker contracts deployed") l.Info().Msg("Successfully deployed all PerformDataChecker Contracts") return upkeeps } +// DeployUpkeepCounters sequentially deploys a set amount of upkeep counter contracts. func DeployUpkeepCounters( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, testRange *big.Int, interval *big.Int, @@ -524,7 +506,7 @@ func DeployUpkeepCounters( for contractCount := 0; contractCount < numberOfContracts; contractCount++ { // Deploy consumer - upkeepCounter, err := contractDeployer.DeployUpkeepCounter(testRange, interval) + upkeepCounter, err := contracts.DeployUpkeepCounter(client, testRange, interval) require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) upkeepCounters = append(upkeepCounters, upkeepCounter) l.Debug(). @@ -532,22 +514,17 @@ func DeployUpkeepCounters( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed Keeper Consumer Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumer deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return upkeepCounters } +// DeployUpkeepPerformCounter sequentially deploys a set amount of upkeep perform counter restrictive contracts. func DeployUpkeepPerformCounterRestrictive( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + client *seth.Client, numberOfContracts int, testRange *big.Int, averageEligibilityCadence *big.Int, @@ -557,7 +534,7 @@ func DeployUpkeepPerformCounterRestrictive( for contractCount := 0; contractCount < numberOfContracts; contractCount++ { // Deploy consumer - upkeepCounter, err := contractDeployer.DeployUpkeepPerformCounterRestrictive(testRange, averageEligibilityCadence) + upkeepCounter, err := contracts.DeployUpkeepPerformCounterRestrictive(client, testRange, averageEligibilityCadence) require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) upkeepCounters = append(upkeepCounters, upkeepCounter) l.Debug(). @@ -565,39 +542,89 @@ func DeployUpkeepPerformCounterRestrictive( Int("Number", contractCount+1). Int("Out Of", numberOfContracts). Msg("Deployed Keeper Consumer Contract") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for KeeperConsumer deployments") - } } - err := client.WaitForEvents() - require.NoError(t, err, "Failed waiting for to deploy all keeper consumer contracts") + require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") return upkeepCounters } -// RegisterNewUpkeeps registers the given amount of new upkeeps, using the registry and registrar -// which are passed as parameters. -// It returns the newly deployed contracts (consumers), as well as their upkeep IDs. +// RegisterNewUpkeeps concurrently registers the given amount of new upkeeps, using the registry and registrar, +// which are passed as parameters. It returns the newly deployed contracts (consumers), as well as their upkeep IDs. func RegisterNewUpkeeps( t *testing.T, - contractDeployer contracts.ContractDeployer, - client blockchain.EVMClient, + chainClient *seth.Client, linkToken contracts.LinkToken, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, upkeepGasLimit uint32, numberOfNewUpkeeps int, ) ([]contracts.KeeperConsumer, []*big.Int) { - newlyDeployedUpkeeps := DeployKeeperConsumers(t, contractDeployer, client, numberOfNewUpkeeps, false, false) + newlyDeployedUpkeeps := DeployKeeperConsumers(t, chainClient, numberOfNewUpkeeps, false, false) var addressesOfNewUpkeeps []string for _, upkeep := range newlyDeployedUpkeeps { addressesOfNewUpkeeps = append(addressesOfNewUpkeeps, upkeep.Address()) } - newUpkeepIDs := RegisterUpkeepContracts(t, linkToken, big.NewInt(9e18), client, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) + concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) + require.NoError(t, err, "Insufficient concurrency to execute action") + + operationsPerAddress := numberOfNewUpkeeps / concurrency + + multicallAddress, err := contracts.DeployMultiCallContract(chainClient) + require.NoError(t, err, "Error deploying multicall contract") + + linkFundsForEachUpkeep := big.NewInt(9e18) + + err = SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfNewUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) + require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") + + newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) return newlyDeployedUpkeeps, newUpkeepIDs } + +var INSUFFICIENT_EPHEMERAL_KEYS = ` +Error: Insufficient Ephemeral Addresses for Simulated Network + +To operate on a simulated network, you must configure at least one ephemeral address. Currently, %d ephemeral address(es) are set. Please update your TOML configuration file as follows to meet this requirement: +[Seth] ephemeral_addresses_number = 1 + +This adjustment ensures that your setup is minimaly viable. Although it is highly recommended to use at least 20 ephemeral addresses. +` + +var INSUFFICIENT_STATIC_KEYS = ` +Error: Insufficient Private Keys for Live Network + +To run this test on a live network, you must either: +1. Set at least two private keys in the '[Network.WalletKeys]' section of your TOML configuration file. Example format: + [Network.WalletKeys] + NETWORK_NAME=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] +2. Set at least two private keys in the '[Network.EVMNetworks.NETWORK_NAME] section of your TOML configuration file. Example format: + evm_keys=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] + +Currently, only %d private key/s is/are set. + +Recommended Action: +Distribute your funds across multiple private keys and update your configuration accordingly. Even though 1 private key is sufficient for testing, it is highly recommended to use at least 10 private keys. +` + +// GetAndAssertCorrectConcurrency checks Seth configuration for the number of ephemeral keys or static keys (depending on Seth configuration) and makes sure that +// the number is at least minConcurrency. If the number is less than minConcurrency, it returns an error. The root key is always excluded from the count. +func GetAndAssertCorrectConcurrency(client *seth.Client, minConcurrency int) (int, error) { + concurrency := client.Cfg.GetMaxConcurrency() + + var msg string + if client.Cfg.IsSimulatedNetwork() { + msg = fmt.Sprintf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) + } else { + msg = fmt.Sprintf(INSUFFICIENT_STATIC_KEYS, concurrency) + } + + if concurrency < minConcurrency { + return 0, fmt.Errorf(msg) + } + + return concurrency, nil +} diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index e5f9beff74..0f8dd9b29f 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -4,14 +4,12 @@ import ( "crypto/ed25519" "encoding/hex" "fmt" - "math/big" "strings" "time" "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" @@ -20,7 +18,6 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -32,82 +29,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) -// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployOCRv2Contracts -func DeployOCRv2Contracts( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - transmitters []string, - client blockchain.EVMClient, - ocrOptions contracts.OffchainOptions, -) ([]contracts.OffchainAggregatorV2, error) { - var ocrInstances []contracts.OffchainAggregatorV2 - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffchainAggregatorV2( - linkTokenContract.Address(), - ocrOptions, - ) - if err != nil { - return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for OCRv2 contract deployments: %w", err) - } - } - } - err := client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCRv2 contract deployments: %w", err) - } - - // Gather address payees - var payees []string - for range transmitters { - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR payees: %w", err) - } - } - } - return ocrInstances, client.WaitForEvents() -} - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.ConfigureOCRv2AggregatorContracts -func ConfigureOCRv2AggregatorContracts( - client blockchain.EVMClient, - contractConfig *contracts.OCRv2Config, - ocrv2Contracts []contracts.OffchainAggregatorV2, -) error { - for contractCount, ocrInstance := range ocrv2Contracts { - // Exclude the first node, which will be used as a bootstrapper - err := ocrInstance.SetConfig(contractConfig) - if err != nil { - return fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for setting OCR config: %w", err) - } - } - } - return client.WaitForEvents() -} - // BuildMedianOCR2Config builds a default OCRv2 config for the given chainlink nodes for a standard median aggregation job func BuildMedianOCR2Config( workerNodes []*client.ChainlinkK8sClient, @@ -371,53 +292,6 @@ func CreateOCRv2Jobs( return nil } -// StartNewOCR2Round requests a new round from the ocr2 contracts and waits for confirmation -func StartNewOCR2Round( - roundNumber int64, - ocrInstances []contracts.OffchainAggregatorV2, - client blockchain.EVMClient, - timeout time.Duration, - logger zerolog.Logger, -) error { - time.Sleep(5 * time.Second) - for i := 0; i < len(ocrInstances); i++ { - err := ocrInstances[i].RequestNewRound() - if err != nil { - return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) - } - ocrRound := contracts.NewOffchainAggregatorV2RoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), timeout, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err = ocrRound.Wait() // wait for OCR Round to complete - if err != nil { - return fmt.Errorf("failed to wait for OCR Round %d to complete instance %d", roundNumber, i) - } - if !ocrRound.Complete() { - return fmt.Errorf("failed to complete OCR Round %d for ocr instance %d", roundNumber, i) - } - } - return nil -} - -// WatchNewOCR2Round is the same as StartNewOCR2Round but does NOT explicitly request a new round -// as that can cause odd behavior in tandem with changing adapter values in OCR2 -func WatchNewOCR2Round( - roundNumber int64, - ocrInstances []contracts.OffchainAggregatorV2, - client blockchain.EVMClient, - timeout time.Duration, - logger zerolog.Logger, -) error { - for i := 0; i < len(ocrInstances); i++ { - ocrRound := contracts.NewOffchainAggregatorV2RoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), timeout, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err := client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) - } - } - return nil -} - // SetOCR2AdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node // used for OCR2 tests func SetOCR2AdapterResponse( @@ -460,34 +334,6 @@ func SetOCR2AllAdapterResponsesToTheSameValue( return eg.Wait() } -// SetOCR2AllAdapterResponsesToDifferentValues sets the mock responses in mockserver that are read by chainlink nodes -// to simulate different adapters. This sets all adapter responses for each node and contract to different responses -// used for OCR2 tests -func SetOCR2AllAdapterResponsesToDifferentValues( - responses []int, - ocrInstances []contracts.OffchainAggregatorV2, - chainlinkNodes []*client.ChainlinkK8sClient, - mockserver *ctfClient.MockserverClient, -) error { - if len(responses) != len(ocrInstances)*len(chainlinkNodes) { - return fmt.Errorf( - "amount of responses %d should be equal to the amount of OCR instances %d times the amount of Chainlink nodes %d", - len(responses), len(ocrInstances), len(chainlinkNodes), - ) - } - eg := &errgroup.Group{} - for _, o := range ocrInstances { - ocrInstance := o - for ni := 1; ni < len(chainlinkNodes); ni++ { - nodeIndex := ni - eg.Go(func() error { - return SetOCR2AdapterResponse(responses[nodeIndex-1], ocrInstance, chainlinkNodes[nodeIndex], mockserver) - }) - } - } - return eg.Wait() -} - // BuildOCR2NodeContractPairID builds a UUID based on a related pair of a Chainlink node and OCRv2 contract func BuildOCR2NodeContractPairID(node *client.ChainlinkK8sClient, ocrInstance contracts.OffchainAggregatorV2) (string, error) { if node == nil { diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go index 8a0a02c050..733b690355 100644 --- a/integration-tests/actions/ocr2_helpers_local.go +++ b/integration-tests/actions/ocr2_helpers_local.go @@ -132,6 +132,9 @@ func CreateOCRv2JobsLocal( ocrSpec.OCR2OracleSpec.RelayConfig["chainReader"] = evmtypes.ChainReaderConfig{ Contracts: map[string]evmtypes.ChainContractReader{ "median": { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{"LatestRoundRequested"}, + }, ContractABI: `[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"},{"indexed":false,"internalType":"uint8","name":"round","type":"uint8"}],"name":"RoundRequested","type":"event"},{"inputs":[],"name":"latestTransmissionDetails","outputs":[{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"},{"internalType":"uint8","name":"round","type":"uint8"},{"internalType":"int192","name":"latestAnswer_","type":"int192"},{"internalType":"uint64","name":"latestTimestamp_","type":"uint64"}],"stateMutability":"view","type":"function"}]`, Configs: map[string]*evmtypes.ChainReaderDefinition{ "LatestTransmissionDetails": { diff --git a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go index 61989def0c..cda6fa72ca 100644 --- a/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go +++ b/integration-tests/actions/ocr2vrf_actions/ocr2vrf_steps.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -322,7 +322,7 @@ func SetupOCR2VRFUniverse( // fund OCR Nodes (so that they can transmit) nodes := contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes) - err = actions_seth.FundChainlinkNodesFromRootAddress(l, chainClient, nodes, ocr2vrf_constants.EthFundingAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, nodes, ocr2vrf_constants.EthFundingAmount) require.NoError(t, err, "Error funding Nodes") bootstrapNode := chainlinkNodes[0] diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index 89a9d1574d..6e54e81cd8 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -2,17 +2,13 @@ package actions import ( "fmt" - "math/big" "strings" "testing" - "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/rs/zerolog" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -22,163 +18,6 @@ import ( // This actions file often returns functions, rather than just values. These are used as common test helpers, and are // handy to have returning as functions so that Ginkgo can use them in an aesthetically pleasing way. -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployOCRContracts -func DeployOCRContracts( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkK8sClient, - client blockchain.EVMClient, -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for OCR contract deployments: %w", err) - } - } - } - err := client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contract deployments: %w", err) - } - - // Gather transmitter and address payees - var transmitters, payees []string - for _, node := range workerNodes { - addr, err := node.PrimaryEthAddress() - if err != nil { - return nil, fmt.Errorf("error getting node's primary ETH address: %w", err) - } - transmitters = append(transmitters, addr) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR payees: %w", err) - } - } - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contracts to set payees and transmitters: %w", err) - } - - // Set Config - transmitterAddresses, err := ChainlinkNodeAddresses(workerNodes) - if err != nil { - return nil, fmt.Errorf("getting node common addresses should not fail: %w", err) - } - for contractCount, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - transmitterAddresses, - ) - if err != nil { - return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR config: %w", err) - } - } - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contracts to set config: %w", err) - } - return ocrInstances, nil -} - -// DeployOCRContractsForwarderFlow deploys and funds a certain number of offchain -// aggregator contracts with forwarders as effectiveTransmitters -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployOCRContractsForwarderFlow -func DeployOCRContractsForwarderFlow( - t *testing.T, - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkK8sClient, - forwarderAddresses []common.Address, - client blockchain.EVMClient, -) []contracts.OffchainAggregator { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - require.NoError(t, err, "Deploying OCR instance %d shouldn't fail", contractCount+1) - ocrInstances = append(ocrInstances, ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for OCR Contract deployments") - } - } - err := client.WaitForEvents() - require.NoError(t, err, "Error waiting for OCR contract deployments") - - // Gather transmitter and address payees - var transmitters, payees []string - for _, forwarderCommonAddress := range forwarderAddresses { - forwarderAddress := forwarderCommonAddress.Hex() - transmitters = append(transmitters, forwarderAddress) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - require.NoError(t, err, "Error setting OCR payees") - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for setting OCR payees") - } - } - err = client.WaitForEvents() - require.NoError(t, err, "Error waiting for OCR contracts to set payees and transmitters") - - // Set Config - for contractCount, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - forwarderAddresses, - ) - require.NoError(t, err, "Error setting OCR config for contract '%d'", ocrInstance.Address()) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - err = client.WaitForEvents() - require.NoError(t, err, "Failed to wait for setting OCR config") - } - } - err = client.WaitForEvents() - require.NoError(t, err, "Error waiting for OCR contracts to set config") - return ocrInstances -} - // CreateOCRJobs bootstraps the first node and to the other nodes sends ocr jobs that // read from different adapters, to be used in combination with SetAdapterResponses func CreateOCRJobs( @@ -322,49 +161,6 @@ func CreateOCRJobsWithForwarder( } } -// StartNewRound requests a new round from the ocr contracts and waits for confirmation -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.StartNewRound -func StartNewRound( - roundNumber int64, - ocrInstances []contracts.OffchainAggregator, - client blockchain.EVMClient, - logger zerolog.Logger, -) error { - for i := 0; i < len(ocrInstances); i++ { - err := ocrInstances[i].RequestNewRound() - if err != nil { - return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) - } - ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), client.GetNetworkConfig().Timeout.Duration, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err = client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) - } - } - return nil -} - -// WatchNewRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new -// round from the contract, as this can cause some odd behavior in some cases -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.WatchNewRound -func WatchNewRound( - roundNumber int64, - ocrInstances []contracts.OffchainAggregator, - client blockchain.EVMClient, - logger zerolog.Logger, -) error { - for i := 0; i < len(ocrInstances); i++ { - ocrRound := contracts.NewOffchainAggregatorRoundConfirmer(ocrInstances[i], big.NewInt(roundNumber), client.GetNetworkConfig().Timeout.Duration, logger) - client.AddHeaderEventSubscription(ocrInstances[i].Address(), ocrRound) - err := client.WaitForEvents() - if err != nil { - return fmt.Errorf("failed to wait for event subscriptions of OCR instance %d: %w", i+1, err) - } - } - return nil -} - // SetAdapterResponse sets a single adapter response that correlates with an ocr contract and a chainlink node func SetAdapterResponse( response int, @@ -405,33 +201,6 @@ func SetAllAdapterResponsesToTheSameValue( return eg.Wait() } -// SetAllAdapterResponsesToDifferentValues sets the mock responses in mockserver that are read by chainlink nodes -// to simulate different adapters. This sets all adapter responses for each node and contract to different responses -func SetAllAdapterResponsesToDifferentValues( - responses []int, - ocrInstances []contracts.OffchainAggregator, - chainlinkNodes []*client.ChainlinkK8sClient, - mockserver *ctfClient.MockserverClient, -) error { - if len(responses) != len(ocrInstances)*len(chainlinkNodes) { - return fmt.Errorf( - "amount of responses %d should be equal to the amount of OCR instances %d times the amount of Chainlink nodes %d", - len(responses), len(ocrInstances), len(chainlinkNodes), - ) - } - eg := &errgroup.Group{} - for _, o := range ocrInstances { - ocrInstance := o - for ni := 1; ni < len(chainlinkNodes); ni++ { - nodeIndex := ni - eg.Go(func() error { - return SetAdapterResponse(responses[nodeIndex-1], ocrInstance, chainlinkNodes[nodeIndex], mockserver) - }) - } - } - return eg.Wait() -} - // BuildNodeContractPairID builds a UUID based on a related pair of a Chainlink node and OCR contract func BuildNodeContractPairID(node contracts.ChainlinkNodeWithKeysAndAddress, ocrInstance contracts.OffchainAggregator) (string, error) { if node == nil { diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index 1a7371517a..0b415277f2 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -6,13 +6,10 @@ import ( "net/http" "strings" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/rs/zerolog" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -24,32 +21,6 @@ import ( Please, use them while refactoring other tests to local docker env */ -// FundChainlinkNodesLocal will fund all the provided Chainlink nodes with a set amount of native currency -func FundChainlinkNodesLocal( - nodes []*client.ChainlinkClient, - client blockchain.EVMClient, - amount *big.Float, -) error { - for _, cl := range nodes { - toAddress, err := cl.PrimaryEthAddress() - if err != nil { - return err - } - toAddr := common.HexToAddress(toAddress) - gasEstimates, err := client.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - err = client.Fund(toAddress, amount, gasEstimates) - if err != nil { - return err - } - } - return client.WaitForEvents() -} - func ChainlinkNodeAddressesLocal(nodes []*client.ChainlinkClient) ([]common.Address, error) { addresses := make([]common.Address, 0) for _, node := range nodes { @@ -62,85 +33,6 @@ func ChainlinkNodeAddressesLocal(nodes []*client.ChainlinkClient) ([]common.Addr return addresses, nil } -func DeployOCRContractsLocal( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkClient, - client blockchain.EVMClient, -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for OCR contract deployments: %w", err) - } - } - err := client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contract deployments: %w", err) - } - - // Gather transmitter and address payees - var transmitters, payees []string - for _, node := range workerNodes { - addr, err := node.PrimaryEthAddress() - if err != nil { - return nil, fmt.Errorf("error getting node's primary ETH address: %w", err) - } - transmitters = append(transmitters, addr) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for _, ocrInstance := range ocrInstances { - err = ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR payees: %w", err) - } - } - - // Set Config - transmitterAddresses, err := ChainlinkNodeAddressesLocal(workerNodes) - if err != nil { - return nil, fmt.Errorf("getting node common addresses should not fail: %w", err) - } - - for _, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - transmitterAddresses, - ) - if err != nil { - return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("failed to wait for setting OCR config: %w", err) - } - } - err = client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("error waiting for OCR contracts to set config: %w", err) - } - return ocrInstances, nil -} - func CreateOCRJobsLocal( ocrInstances []contracts.OffchainAggregator, bootstrapNode *client.ChainlinkClient, @@ -256,92 +148,6 @@ func SetAllAdapterResponsesToTheSameValueLocal( return eg.Wait() } -func TrackForwarderLocal( - chainClient blockchain.EVMClient, - authorizedForwarder common.Address, - node *client.ChainlinkClient, - logger zerolog.Logger, -) error { - chainID := chainClient.GetChainID() - _, _, err := node.TrackForwarder(chainID, authorizedForwarder) - if err != nil { - return fmt.Errorf("failed to track forwarder, err: %w", err) - } - logger.Info().Str("NodeURL", node.Config.URL). - Str("ForwarderAddress", authorizedForwarder.Hex()). - Str("ChaindID", chainID.String()). - Msg("Forwarder tracked") - return nil -} - -func DeployOCRContractsForwarderFlowLocal( - numberOfContracts int, - linkTokenContract contracts.LinkToken, - contractDeployer contracts.ContractDeployer, - workerNodes []*client.ChainlinkClient, - forwarderAddresses []common.Address, - client blockchain.EVMClient, -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contractDeployer.DeployOffChainAggregator( - linkTokenContract.Address(), - contracts.DefaultOffChainAggregatorOptions(), - ) - if err != nil { - return nil, fmt.Errorf("failed to deploy offchain aggregator, err: %w", err) - } - ocrInstances = append(ocrInstances, ocrInstance) - err = client.WaitForEvents() - if err != nil { - return nil, err - } - } - if err := client.WaitForEvents(); err != nil { - return nil, err - } - - // Gather transmitter and address payees - var transmitters, payees []string - for _, forwarderCommonAddress := range forwarderAddresses { - forwarderAddress := forwarderCommonAddress.Hex() - transmitters = append(transmitters, forwarderAddress) - payees = append(payees, client.GetDefaultWallet().Address()) - } - - // Set Payees - for _, ocrInstance := range ocrInstances { - err := ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("failed to set OCR payees, err: %w", err) - } - if err := client.WaitForEvents(); err != nil { - return nil, err - } - } - if err := client.WaitForEvents(); err != nil { - return nil, err - } - - // Set Config - for _, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err := ocrInstance.SetConfig( - contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - forwarderAddresses, - ) - if err != nil { - return nil, fmt.Errorf("failed to set on-chain config, err: %w", err) - } - if err = client.WaitForEvents(); err != nil { - return nil, err - } - } - return ocrInstances, client.WaitForEvents() -} - func CreateOCRJobsWithForwarderLocal( ocrInstances []contracts.OffchainAggregator, bootstrapNode *client.ChainlinkClient, diff --git a/integration-tests/actions/operator_forwarder_helpers.go b/integration-tests/actions/operator_forwarder_helpers.go deleted file mode 100644 index 31eed7b7aa..0000000000 --- a/integration-tests/actions/operator_forwarder_helpers.go +++ /dev/null @@ -1,198 +0,0 @@ -package actions - -import ( - "math/big" - "testing" - - geth "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" -) - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.DeployForwarderContracts -func DeployForwarderContracts( - t *testing.T, - contractDeployer contracts.ContractDeployer, - linkToken contracts.LinkToken, - chainClient blockchain.EVMClient, - numberOfOperatorForwarderPairs int, -) (operators []common.Address, authorizedForwarders []common.Address, operatorFactoryInstance contracts.OperatorFactory) { - operatorFactoryInstance, err := contractDeployer.DeployOperatorFactory(linkToken.Address()) - require.NoError(t, err, "Deploying OperatorFactory Contract shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Failed waiting for deployment of flux aggregator contract") - - operatorCreated := make(chan *operator_factory.OperatorFactoryOperatorCreated) - authorizedForwarderCreated := make(chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated) - for i := 0; i < numberOfOperatorForwarderPairs; i++ { - SubscribeOperatorFactoryEvents(t, authorizedForwarderCreated, operatorCreated, chainClient, operatorFactoryInstance) - _, err = operatorFactoryInstance.DeployNewOperatorAndForwarder() - require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for events in nodes shouldn't fail") - eventDataAuthorizedForwarder, eventDataOperatorCreated := <-authorizedForwarderCreated, <-operatorCreated - operator, authorizedForwarder := eventDataOperatorCreated.Operator, eventDataAuthorizedForwarder.Forwarder - operators = append(operators, operator) - authorizedForwarders = append(authorizedForwarders, authorizedForwarder) - } - err = chainClient.WaitForEvents() - require.NoError(t, err, "Error waiting for events") - return operators, authorizedForwarders, operatorFactoryInstance -} - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.AcceptAuthorizedReceiversOperator -func AcceptAuthorizedReceiversOperator( - t *testing.T, - operator common.Address, - authorizedForwarder common.Address, - nodeAddresses []common.Address, - chainClient blockchain.EVMClient, - contractLoader contracts.ContractLoader, -) { - operatorInstance, err := contractLoader.LoadOperatorContract(operator) - require.NoError(t, err, "Loading operator contract shouldn't fail") - forwarderInstance, err := contractLoader.LoadAuthorizedForwarder(authorizedForwarder) - require.NoError(t, err, "Loading authorized forwarder contract shouldn't fail") - - err = operatorInstance.AcceptAuthorizedReceivers([]common.Address{authorizedForwarder}, nodeAddresses) - require.NoError(t, err, "Accepting authorized receivers shouldn't fail") - err = chainClient.WaitForEvents() - require.NoError(t, err, "Waiting for events in nodes shouldn't fail") - - senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized senders shouldn't fail") - var nodesAddrs []string - for _, o := range nodeAddresses { - nodesAddrs = append(nodesAddrs, o.Hex()) - } - require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses") - - owner, err := forwarderInstance.Owner(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail") - require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator") -} - -func ProcessNewEvent( - t *testing.T, - operatorCreated chan *operator_factory.OperatorFactoryOperatorCreated, - authorizedForwarderCreated chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated, - event *types.Log, - eventDetails *abi.Event, - operatorFactoryInstance contracts.OperatorFactory, - chainClient blockchain.EVMClient, -) { - l := logging.GetTestLogger(t) - errorChan := make(chan error) - eventConfirmed := make(chan bool) - err := chainClient.ProcessEvent(eventDetails.Name, event, eventConfirmed, errorChan) - if err != nil { - l.Error().Err(err).Str("Hash", event.TxHash.Hex()).Str("Event", eventDetails.Name).Msg("Error trying to process event") - return - } - l.Debug(). - Str("Event", eventDetails.Name). - Str("Address", event.Address.Hex()). - Str("Hash", event.TxHash.Hex()). - Msg("Attempting to Confirm Event") - for { - select { - case err := <-errorChan: - l.Error().Err(err).Msg("Error while confirming event") - return - case confirmed := <-eventConfirmed: - if confirmed { - if eventDetails.Name == "AuthorizedForwarderCreated" { // AuthorizedForwarderCreated event to authorizedForwarderCreated channel to handle in main loop - eventData, err := operatorFactoryInstance.ParseAuthorizedForwarderCreated(*event) - require.NoError(t, err, "Parsing OperatorFactoryAuthorizedForwarderCreated event log in "+ - "OperatorFactory instance shouldn't fail") - authorizedForwarderCreated <- eventData - } - if eventDetails.Name == "OperatorCreated" { // OperatorCreated event to operatorCreated channel to handle in main loop - eventData, err := operatorFactoryInstance.ParseOperatorCreated(*event) - require.NoError(t, err, "Parsing OperatorFactoryAuthorizedForwarderCreated event log in "+ - "OperatorFactory instance shouldn't fail") - operatorCreated <- eventData - } - } - return - } - } -} - -// SubscribeOperatorFactoryEvents subscribes to the event log for authorizedForwarderCreated and operatorCreated events -// from OperatorFactory contract -func SubscribeOperatorFactoryEvents( - t *testing.T, - authorizedForwarderCreated chan *operator_factory.OperatorFactoryAuthorizedForwarderCreated, - operatorCreated chan *operator_factory.OperatorFactoryOperatorCreated, - chainClient blockchain.EVMClient, - operatorFactoryInstance contracts.OperatorFactory, -) { - l := logging.GetTestLogger(t) - contractABI, err := operator_factory.OperatorFactoryMetaData.GetAbi() - require.NoError(t, err, "Getting contract abi for OperatorFactory shouldn't fail") - latestBlockNum, err := chainClient.LatestBlockNumber(testcontext.Get(t)) - require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail") - query := geth.FilterQuery{ - FromBlock: big.NewInt(0).SetUint64(latestBlockNum), - Addresses: []common.Address{common.HexToAddress(operatorFactoryInstance.Address())}, - } - - eventLogs := make(chan types.Log) - sub, err := chainClient.SubscribeFilterLogs(testcontext.Get(t), query, eventLogs) - require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail") - go func() { - defer sub.Unsubscribe() - remainingExpectedEvents := 2 - for { - select { - case err := <-sub.Err(): - l.Error().Err(err).Msg("Error while watching for new contract events. Retrying Subscription") - sub.Unsubscribe() - - sub, err = chainClient.SubscribeFilterLogs(testcontext.Get(t), query, eventLogs) - require.NoError(t, err, "Subscribing to contract event log for OperatorFactory instance shouldn't fail") - case vLog := <-eventLogs: - eventDetails, err := contractABI.EventByID(vLog.Topics[0]) - require.NoError(t, err, "Getting event details for OperatorFactory instance shouldn't fail") - go ProcessNewEvent( - t, operatorCreated, authorizedForwarderCreated, &vLog, - eventDetails, operatorFactoryInstance, chainClient, - ) - if eventDetails.Name == "AuthorizedForwarderCreated" || eventDetails.Name == "OperatorCreated" { - remainingExpectedEvents-- - if remainingExpectedEvents <= 0 { - return - } - } - } - } - }() -} - -// Deprecated: we are moving away from blockchain.EVMClient, use actions_seth.TrackForwarder -func TrackForwarder( - t *testing.T, - chainClient blockchain.EVMClient, - authorizedForwarder common.Address, - node *client.ChainlinkK8sClient, -) { - l := logging.GetTestLogger(t) - chainID := chainClient.GetChainID() - _, _, err := node.TrackForwarder(chainID, authorizedForwarder) - require.NoError(t, err, "Forwarder track should be created") - l.Info().Str("NodeURL", node.Config.URL). - Str("ForwarderAddress", authorizedForwarder.Hex()). - Str("ChaindID", chainID.String()). - Msg("Forwarder tracked") -} diff --git a/integration-tests/actions/seth/refund.go b/integration-tests/actions/refund.go similarity index 99% rename from integration-tests/actions/seth/refund.go rename to integration-tests/actions/refund.go index bd15fe7a0c..38c4dfad3b 100644 --- a/integration-tests/actions/seth/refund.go +++ b/integration-tests/actions/refund.go @@ -1,4 +1,4 @@ -package actions_seth +package actions import ( "context" @@ -234,7 +234,7 @@ func (r *OvershotTransferRetrier) Retry(ctx context.Context, logger zerolog.Logg // insufficient funds, and retrying with a higher gas limit if the transaction fails due to gas too low. func ReturnFundsFromNodes(log zerolog.Logger, client *seth.Client, chainlinkNodes []contracts.ChainlinkNodeWithKeysAndAddress) error { if client == nil { - return fmt.Errorf("Seth client is nil, unable to return funds from chainlink nodes") + return fmt.Errorf("seth client is nil, unable to return funds from chainlink nodes") } log.Info().Msg("Attempting to return Chainlink node funds to default network wallets") if client.Cfg.IsSimulatedNetwork() { @@ -243,8 +243,7 @@ func ReturnFundsFromNodes(log zerolog.Logger, client *seth.Client, chainlinkNode return nil } - failedReturns := []common.Address{} - + var failedReturns []common.Address for _, chainlinkNode := range chainlinkNodes { fundedKeys, err := chainlinkNode.ExportEVMKeysForChain(fmt.Sprint(client.ChainID)) if err != nil { diff --git a/integration-tests/actions/seth/actions.go b/integration-tests/actions/seth/actions.go deleted file mode 100644 index 68f6df9b49..0000000000 --- a/integration-tests/actions/seth/actions.go +++ /dev/null @@ -1,1118 +0,0 @@ -package actions_seth - -import ( - "context" - "crypto/ecdsa" - "fmt" - "math" - "math/big" - "strings" - "testing" - "time" - - geth "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rpc" - "github.com/pkg/errors" - "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - "github.com/test-go/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -) - -var ContractDeploymentInterval = 200 - -// FundChainlinkNodesFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node -// from root private key. It returns an error if any of the transactions failed. -func FundChainlinkNodesFromRootAddress( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - amount *big.Float, -) error { - if len(client.PrivateKeys) == 0 { - return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) - } - - return FundChainlinkNodes(logger, client, nodes, client.PrivateKeys[0], amount) -} - -// FundChainlinkNodes sends native token amount (expressed in human-scale) to each Chainlink Node -// from private key's address. It returns an error if any of the transactions failed. -func FundChainlinkNodes( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - privateKey *ecdsa.PrivateKey, - amount *big.Float, -) error { - keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { - return cl.PrimaryEthAddress() - } - return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) -} - -// FundChainlinkNodesAtKeyIndexFromRootAddress sends native token amount (expressed in human-scale) to each Chainlink Node -// from root private key.It returns an error if any of the transactions failed. It sends the funds to -// node address at keyIndex (as each node can have multiple addresses). -func FundChainlinkNodesAtKeyIndexFromRootAddress( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - amount *big.Float, - keyIndex int, -) error { - if len(client.PrivateKeys) == 0 { - return errors.Wrap(errors.New(seth.ErrNoKeyLoaded), fmt.Sprintf("requested key: %d", 0)) - } - - return FundChainlinkNodesAtKeyIndex(logger, client, nodes, client.PrivateKeys[0], amount, keyIndex) -} - -// FundChainlinkNodesAtKeyIndex sends native token amount (expressed in human-scale) to each Chainlink Node -// from private key's address. It returns an error if any of the transactions failed. It sends the funds to -// node address at keyIndex (as each node can have multiple addresses). -func FundChainlinkNodesAtKeyIndex( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - privateKey *ecdsa.PrivateKey, - amount *big.Float, - keyIndex int, -) error { - keyAddressFn := func(cl contracts.ChainlinkNodeWithKeysAndAddress) (string, error) { - toAddress, err := cl.EthAddresses() - if err != nil { - return "", err - } - return toAddress[keyIndex], nil - } - return fundChainlinkNodesAtAnyKey(logger, client, nodes, privateKey, amount, keyAddressFn) -} - -func fundChainlinkNodesAtAnyKey( - logger zerolog.Logger, - client *seth.Client, - nodes []contracts.ChainlinkNodeWithKeysAndAddress, - privateKey *ecdsa.PrivateKey, - amount *big.Float, - keyAddressFn func(contracts.ChainlinkNodeWithKeysAndAddress) (string, error), -) error { - for _, cl := range nodes { - toAddress, err := keyAddressFn(cl) - if err != nil { - return err - } - - fromAddress, err := privateKeyToAddress(privateKey) - if err != nil { - return err - } - - receipt, err := SendFunds(logger, client, FundsToSendPayload{ - ToAddress: common.HexToAddress(toAddress), - Amount: conversions.EtherToWei(amount), - PrivateKey: privateKey, - }) - if err != nil { - logger.Err(err). - Str("From", fromAddress.Hex()). - Str("To", toAddress). - Msg("Failed to fund Chainlink node") - - return err - } - - txHash := "(none)" - if receipt != nil { - txHash = receipt.TxHash.String() - } - - logger.Info(). - Str("From", fromAddress.Hex()). - Str("To", toAddress). - Str("TxHash", txHash). - Str("Amount", amount.String()). - Msg("Funded Chainlink node") - } - - return nil -} - -type FundsToSendPayload struct { - ToAddress common.Address - Amount *big.Int - PrivateKey *ecdsa.PrivateKey - GasLimit *int64 - GasPrice *big.Int - GasFeeCap *big.Int - GasTipCap *big.Int - TxTimeout *time.Duration -} - -// TODO: move to CTF? -// SendFunds sends native token amount (expressed in human-scale) from address controlled by private key -// to given address. You can override any or none of the following: gas limit, gas price, gas fee cap, gas tip cap. -// Values that are not set will be estimated or taken from config. -func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPayload) (*types.Receipt, error) { - fromAddress, err := privateKeyToAddress(payload.PrivateKey) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(context.Background(), client.Cfg.Network.TxnTimeout.Duration()) - nonce, err := client.Client.PendingNonceAt(ctx, fromAddress) - defer cancel() - if err != nil { - return nil, err - } - - var gasLimit int64 - gasLimitRaw, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) - if err != nil { - gasLimit = client.Cfg.Network.TransferGasFee - } else { - gasLimit = int64(gasLimitRaw) - } - - gasPrice := big.NewInt(0) - gasFeeCap := big.NewInt(0) - gasTipCap := big.NewInt(0) - - if payload.GasLimit != nil { - gasLimit = *payload.GasLimit - } - - if client.Cfg.Network.EIP1559DynamicFees { - // if any of the dynamic fees are not set, we need to either estimate them or read them from config - if payload.GasFeeCap == nil || payload.GasTipCap == nil { - // estimation or config reading happens here - txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) - gasFeeCap = txOptions.GasFeeCap - gasTipCap = txOptions.GasTipCap - } - - // override with payload values if they are set - if payload.GasFeeCap != nil { - gasFeeCap = payload.GasFeeCap - } - - if payload.GasTipCap != nil { - gasTipCap = payload.GasTipCap - } - } else { - if payload.GasPrice == nil { - txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) - gasPrice = txOptions.GasPrice - } else { - gasPrice = payload.GasPrice - } - } - - var rawTx types.TxData - - if client.Cfg.Network.EIP1559DynamicFees { - rawTx = &types.DynamicFeeTx{ - Nonce: nonce, - To: &payload.ToAddress, - Value: payload.Amount, - Gas: uint64(gasLimit), - GasFeeCap: gasFeeCap, - GasTipCap: gasTipCap, - } - } else { - rawTx = &types.LegacyTx{ - Nonce: nonce, - To: &payload.ToAddress, - Value: payload.Amount, - Gas: uint64(gasLimit), - GasPrice: gasPrice, - } - } - - signedTx, err := types.SignNewTx(payload.PrivateKey, types.LatestSignerForChainID(big.NewInt(client.ChainID)), rawTx) - - if err != nil { - return nil, errors.Wrap(err, "failed to sign tx") - } - - txTimeout := client.Cfg.Network.TxnTimeout.Duration() - if payload.TxTimeout != nil { - txTimeout = *payload.TxTimeout - } - - logger.Debug(). - Str("From", fromAddress.Hex()). - Str("To", payload.ToAddress.Hex()). - Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). - Uint64("Nonce", nonce). - Int64("Gas Limit", gasLimit). - Str("Gas Price", gasPrice.String()). - Str("Gas Fee Cap", gasFeeCap.String()). - Str("Gas Tip Cap", gasTipCap.String()). - Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). - Msg("About to send funds") - - ctx, cancel = context.WithTimeout(ctx, txTimeout) - defer cancel() - err = client.Client.SendTransaction(ctx, signedTx) - if err != nil { - return nil, errors.Wrap(err, "failed to send transaction") - } - - logger.Debug(). - Str("From", fromAddress.Hex()). - Str("To", payload.ToAddress.Hex()). - Str("TxHash", signedTx.Hash().String()). - Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). - Uint64("Nonce", nonce). - Int64("Gas Limit", gasLimit). - Str("Gas Price", gasPrice.String()). - Str("Gas Fee Cap", gasFeeCap.String()). - Str("Gas Tip Cap", gasTipCap.String()). - Bool("Dynamic fees", client.Cfg.Network.EIP1559DynamicFees). - Msg("Sent funds") - - receipt, receiptErr := client.WaitMined(ctx, logger, client.Client, signedTx) - if receiptErr != nil { - return nil, errors.Wrap(receiptErr, "failed to wait for transaction to be mined") - } - - if receipt.Status == 1 { - return receipt, nil - } - - tx, _, err := client.Client.TransactionByHash(ctx, signedTx.Hash()) - if err != nil { - return nil, errors.Wrap(err, "failed to get transaction by hash ") - } - - _, err = client.Decode(tx, receiptErr) - if err != nil { - return nil, err - } - - return receipt, nil -} - -// DeployForwarderContracts first deploys Operator Factory and then uses it to deploy given number of -// operator and forwarder pairs. It waits for each transaction to be mined and then extracts operator and -// forwarder addresses from emitted events. -func DeployForwarderContracts( - t *testing.T, - seth *seth.Client, - linkTokenAddress common.Address, - numberOfOperatorForwarderPairs int, -) (operators []common.Address, authorizedForwarders []common.Address, operatorFactoryInstance contracts.OperatorFactory) { - instance, err := contracts.DeployEthereumOperatorFactory(seth, linkTokenAddress) - require.NoError(t, err, "failed to create new instance of operator factory") - operatorFactoryInstance = &instance - - for i := 0; i < numberOfOperatorForwarderPairs; i++ { - decodedTx, err := seth.Decode(operatorFactoryInstance.DeployNewOperatorAndForwarder()) - require.NoError(t, err, "Deploying new operator with proposed ownership with forwarder shouldn't fail") - - for i, event := range decodedTx.Events { - require.True(t, len(event.Topics) > 0, fmt.Sprintf("Event %d should have topics", i)) - switch event.Topics[0] { - case operator_factory.OperatorFactoryOperatorCreated{}.Topic().String(): - if address, ok := event.EventData["operator"]; ok { - operators = append(operators, address.(common.Address)) - } else { - require.Fail(t, "Operator address not found in event", event) - } - case operator_factory.OperatorFactoryAuthorizedForwarderCreated{}.Topic().String(): - if address, ok := event.EventData["forwarder"]; ok { - authorizedForwarders = append(authorizedForwarders, address.(common.Address)) - } else { - require.Fail(t, "Forwarder address not found in event", event) - } - } - } - } - return operators, authorizedForwarders, operatorFactoryInstance -} - -// WatchNewOCRRound watches for a new OCR round, similarly to StartNewRound, but it does not explicitly request a new -// round from the contract, as this can cause some odd behavior in some cases. It announces success if latest round -// is >= roundNumber. -func WatchNewOCRRound( - l zerolog.Logger, - seth *seth.Client, - roundNumber int64, - ocrInstances []contracts.OffChainAggregatorWithRounds, - timeout time.Duration, -) error { - confirmed := make(map[string]bool) - timeoutC := time.After(timeout) - ticker := time.NewTicker(time.Millisecond * 200) - defer ticker.Stop() - - l.Info().Msgf("Waiting for round %d to be confirmed by all nodes", roundNumber) - - for { - select { - case <-timeoutC: - return fmt.Errorf("timeout waiting for round %d to be confirmed. %d/%d nodes confirmed it", roundNumber, len(confirmed), len(ocrInstances)) - case <-ticker.C: - for i := 0; i < len(ocrInstances); i++ { - if confirmed[ocrInstances[i].Address()] { - continue - } - ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) - roundData, err := ocrInstances[i].GetLatestRound(ctx) - if err != nil { - cancel() - return fmt.Errorf("getting latest round from OCR instance %d have failed: %w", i+1, err) - } - cancel() - if roundData.RoundId.Cmp(big.NewInt(roundNumber)) >= 0 { - l.Debug().Msgf("OCR instance %d/%d confirmed round %d", i+1, len(ocrInstances), roundNumber) - confirmed[ocrInstances[i].Address()] = true - } - } - if len(confirmed) == len(ocrInstances) { - return nil - } - } - } -} - -// AcceptAuthorizedReceiversOperator sets authorized receivers for each operator contract to -// authorizedForwarder and authorized EA to nodeAddresses. Once done, it confirms that authorizations -// were set correctly. -func AcceptAuthorizedReceiversOperator( - t *testing.T, - logger zerolog.Logger, - seth *seth.Client, - operator common.Address, - authorizedForwarder common.Address, - nodeAddresses []common.Address, -) { - operatorInstance, err := contracts.LoadEthereumOperator(logger, seth, operator) - require.NoError(t, err, "Loading operator contract shouldn't fail") - forwarderInstance, err := contracts.LoadEthereumAuthorizedForwarder(seth, authorizedForwarder) - require.NoError(t, err, "Loading authorized forwarder contract shouldn't fail") - - err = operatorInstance.AcceptAuthorizedReceivers([]common.Address{authorizedForwarder}, nodeAddresses) - require.NoError(t, err, "Accepting authorized forwarder shouldn't fail") - - senders, err := forwarderInstance.GetAuthorizedSenders(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized senders shouldn't fail") - var nodesAddrs []string - for _, o := range nodeAddresses { - nodesAddrs = append(nodesAddrs, o.Hex()) - } - require.Equal(t, nodesAddrs, senders, "Senders addresses should match node addresses") - - owner, err := forwarderInstance.Owner(testcontext.Get(t)) - require.NoError(t, err, "Getting authorized forwarder owner shouldn't fail") - require.Equal(t, operator.Hex(), owner, "Forwarder owner should match operator") -} - -// TrackForwarder creates forwarder track for a given Chainlink node -func TrackForwarder( - t *testing.T, - seth *seth.Client, - authorizedForwarder common.Address, - node contracts.ChainlinkNodeWithForwarder, -) { - l := logging.GetTestLogger(t) - chainID := big.NewInt(seth.ChainID) - _, _, err := node.TrackForwarder(chainID, authorizedForwarder) - require.NoError(t, err, "Forwarder track should be created") - l.Info().Str("NodeURL", node.GetConfig().URL). - Str("ForwarderAddress", authorizedForwarder.Hex()). - Str("ChaindID", chainID.String()). - Msg("Forwarder tracked") -} - -// DeployOCRv2Contracts deploys a number of OCRv2 contracts and configures them with defaults -func DeployOCRv2Contracts( - l zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenAddress common.Address, - transmitters []string, - ocrOptions contracts.OffchainOptions, -) ([]contracts.OffchainAggregatorV2, error) { - var ocrInstances []contracts.OffchainAggregatorV2 - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contracts.DeployOffchainAggregatorV2( - l, - seth, - linkTokenAddress, - ocrOptions, - ) - if err != nil { - return nil, fmt.Errorf("OCRv2 instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, &ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - // Gather address payees - var payees []string - for range transmitters { - payees = append(payees, seth.Addresses[0].Hex()) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err := ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - return ocrInstances, nil -} - -// ConfigureOCRv2AggregatorContracts sets configuration for a number of OCRv2 contracts -func ConfigureOCRv2AggregatorContracts( - contractConfig *contracts.OCRv2Config, - ocrv2Contracts []contracts.OffchainAggregatorV2, -) error { - for contractCount, ocrInstance := range ocrv2Contracts { - // Exclude the first node, which will be used as a bootstrapper - err := ocrInstance.SetConfig(contractConfig) - if err != nil { - return fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - return nil -} - -// TeardownSuite tears down networks/clients and environment and creates a logs folder for failed tests in the -// specified path. Can also accept a testreporter (if one was used) to log further results -func TeardownSuite( - t *testing.T, - chainClient *seth.Client, - env *environment.Environment, - chainlinkNodes []*client.ChainlinkK8sClient, - optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics - failingLogLevel zapcore.Level, // Examines logs after the test, and fails the test if any Chainlink logs are found at or above provided level - grafnaUrlProvider testreporters.GrafanaURLProvider, -) error { - l := logging.GetTestLogger(t) - if err := testreporters.WriteTeardownLogs(t, env, optionalTestReporter, failingLogLevel, grafnaUrlProvider); err != nil { - return fmt.Errorf("Error dumping environment logs, leaving environment running for manual retrieval, err: %w", err) - } - // Delete all jobs to stop depleting the funds - err := DeleteAllJobs(chainlinkNodes) - if err != nil { - l.Warn().Msgf("Error deleting jobs %+v", err) - } - - if chainlinkNodes != nil { - if err := ReturnFundsFromNodes(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { - // This printed line is required for tests that use real funds to propagate the failure - // out to the system running the test. Do not remove - fmt.Println(environment.FAILED_FUND_RETURN) - l.Error().Err(err).Str("Namespace", env.Cfg.Namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - } else { - l.Info().Msg("Successfully returned funds from chainlink nodes to default network wallets") - } - - return env.Shutdown() -} - -// TeardownRemoteSuite sends a report and returns funds from chainlink nodes to network's default wallet -func TeardownRemoteSuite( - t *testing.T, - client *seth.Client, - namespace string, - chainlinkNodes []*client.ChainlinkK8sClient, - optionalTestReporter testreporters.TestReporter, // Optionally pass in a test reporter to log further metrics - grafnaUrlProvider testreporters.GrafanaURLProvider, -) error { - l := logging.GetTestLogger(t) - if err := testreporters.SendReport(t, namespace, "./", optionalTestReporter, grafnaUrlProvider); err != nil { - l.Warn().Err(err).Msg("Error writing test report") - } - // Delete all jobs to stop depleting the funds - err := DeleteAllJobs(chainlinkNodes) - if err != nil { - l.Warn().Msgf("Error deleting jobs %+v", err) - } - - if err = ReturnFundsFromNodes(l, client, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes)); err != nil { - l.Error().Err(err).Str("Namespace", namespace). - Msg("Error attempting to return funds from chainlink nodes to network's default wallet. " + - "Environment is left running so you can try manually!") - } - - return err -} - -// DeleteAllJobs deletes all jobs from all chainlink nodes -// added here temporarily to avoid circular import -func DeleteAllJobs(chainlinkNodes []*client.ChainlinkK8sClient) error { - for _, node := range chainlinkNodes { - if node == nil { - return fmt.Errorf("found a nil chainlink node in the list of chainlink nodes while tearing down: %v", chainlinkNodes) - } - jobs, _, err := node.ReadJobs() - if err != nil { - return fmt.Errorf("error reading jobs from chainlink node, err: %w", err) - } - for _, maps := range jobs.Data { - if _, ok := maps["id"]; !ok { - return fmt.Errorf("error reading job id from chainlink node's jobs %+v", jobs.Data) - } - id := maps["id"].(string) - _, err := node.DeleteJob(id) - if err != nil { - return fmt.Errorf("error deleting job from chainlink node, err: %w", err) - } - } - } - return nil -} - -// StartNewRound requests a new round from the ocr contracts and returns once transaction was mined -func StartNewRound( - ocrInstances []contracts.OffChainAggregatorWithRounds, -) error { - for i := 0; i < len(ocrInstances); i++ { - err := ocrInstances[i].RequestNewRound() - if err != nil { - return fmt.Errorf("requesting new OCR round %d have failed: %w", i+1, err) - } - } - return nil -} - -// DeployOCRContractsForwarderFlow deploys and funds a certain number of offchain -// aggregator contracts with forwarders as effectiveTransmitters -func DeployOCRContractsForwarderFlow( - logger zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenContractAddress common.Address, - workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, - forwarderAddresses []common.Address, -) ([]contracts.OffchainAggregator, error) { - transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { - transmitters = make([]string, 0) - payees = make([]string, 0) - for _, forwarderCommonAddress := range forwarderAddresses { - forwarderAddress := forwarderCommonAddress.Hex() - transmitters = append(transmitters, forwarderAddress) - payees = append(payees, seth.Addresses[0].Hex()) - } - - return - } - - transmitterAddressesFn := func() ([]common.Address, error) { - return forwarderAddresses, nil - } - - return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) -} - -// DeployOCRv1Contracts deploys and funds a certain number of offchain aggregator contracts -func DeployOCRv1Contracts( - logger zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenContractAddress common.Address, - workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, -) ([]contracts.OffchainAggregator, error) { - transmitterPayeesFn := func() (transmitters []string, payees []string, err error) { - transmitters = make([]string, 0) - payees = make([]string, 0) - for _, node := range workerNodes { - var addr string - addr, err = node.PrimaryEthAddress() - if err != nil { - err = fmt.Errorf("error getting node's primary ETH address: %w", err) - return - } - transmitters = append(transmitters, addr) - payees = append(payees, seth.Addresses[0].Hex()) - } - - return - } - - transmitterAddressesFn := func() ([]common.Address, error) { - transmitterAddresses := make([]common.Address, 0) - for _, node := range workerNodes { - primaryAddress, err := node.PrimaryEthAddress() - if err != nil { - return nil, err - } - transmitterAddresses = append(transmitterAddresses, common.HexToAddress(primaryAddress)) - } - - return transmitterAddresses, nil - } - - return deployAnyOCRv1Contracts(logger, seth, numberOfContracts, linkTokenContractAddress, workerNodes, transmitterPayeesFn, transmitterAddressesFn) -} - -func deployAnyOCRv1Contracts( - logger zerolog.Logger, - seth *seth.Client, - numberOfContracts int, - linkTokenContractAddress common.Address, - workerNodes []contracts.ChainlinkNodeWithKeysAndAddress, - getTransmitterAndPayeesFn func() ([]string, []string, error), - getTransmitterAddressesFn func() ([]common.Address, error), -) ([]contracts.OffchainAggregator, error) { - // Deploy contracts - var ocrInstances []contracts.OffchainAggregator - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - ocrInstance, err := contracts.DeployOffchainAggregator(logger, seth, linkTokenContractAddress, contracts.DefaultOffChainAggregatorOptions()) - if err != nil { - return nil, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - ocrInstances = append(ocrInstances, &ocrInstance) - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - // Gather transmitter and address payees - var transmitters, payees []string - var err error - transmitters, payees, err = getTransmitterAndPayeesFn() - if err != nil { - return nil, fmt.Errorf("error getting transmitter and payees: %w", err) - } - - // Set Payees - for contractCount, ocrInstance := range ocrInstances { - err := ocrInstance.SetPayees(transmitters, payees) - if err != nil { - return nil, fmt.Errorf("error settings OCR payees: %w", err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - // Set Config - transmitterAddresses, err := getTransmitterAddressesFn() - if err != nil { - return nil, fmt.Errorf("getting transmitter addresses should not fail: %w", err) - } - - for contractCount, ocrInstance := range ocrInstances { - // Exclude the first node, which will be used as a bootstrapper - err = ocrInstance.SetConfig( - workerNodes, - contracts.DefaultOffChainAggregatorConfig(len(workerNodes)), - transmitterAddresses, - ) - if err != nil { - return nil, fmt.Errorf("error setting OCR config for contract '%s': %w", ocrInstance.Address(), err) - } - if (contractCount+1)%ContractDeploymentInterval == 0 { // For large amounts of contract deployments, space things out some - time.Sleep(2 * time.Second) - } - } - - return ocrInstances, nil -} - -func privateKeyToAddress(privateKey *ecdsa.PrivateKey) (common.Address, error) { - publicKey := privateKey.Public() - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - if !ok { - return common.Address{}, errors.New("error casting public key to ECDSA") - } - return crypto.PubkeyToAddress(*publicKeyECDSA), nil -} - -func WatchNewFluxRound( - l zerolog.Logger, - seth *seth.Client, - roundNumber int64, - fluxInstance contracts.FluxAggregator, - timeout time.Duration, -) error { - timeoutC := time.After(timeout) - ticker := time.NewTicker(time.Millisecond * 200) - defer ticker.Stop() - - l.Info().Msgf("Waiting for flux round %d to be confirmed by flux aggregator", roundNumber) - - for { - select { - case <-timeoutC: - return fmt.Errorf("timeout waiting for round %d to be confirmed", roundNumber) - case <-ticker.C: - ctx, cancel := context.WithTimeout(context.Background(), seth.Cfg.Network.TxnTimeout.Duration()) - roundId, err := fluxInstance.LatestRoundID(ctx) - if err != nil { - cancel() - return fmt.Errorf("getting latest round from flux instance has failed: %w", err) - } - cancel() - if roundId.Cmp(big.NewInt(roundNumber)) >= 0 { - l.Debug().Msgf("Flux instance confirmed round %d", roundNumber) - return nil - } - } - } -} - -// EstimateCostForChainlinkOperations estimates the cost of running a number of operations on the Chainlink node based on estimated gas costs. It supports -// both legacy and EIP-1559 transactions. -func EstimateCostForChainlinkOperations(l zerolog.Logger, client *seth.Client, network blockchain.EVMNetwork, amountOfOperations int) (*big.Float, error) { - bigAmountOfOperations := big.NewInt(int64(amountOfOperations)) - estimations := client.CalculateGasEstimations(client.NewDefaultGasEstimationRequest()) - - gasLimit := network.GasEstimationBuffer + network.ChainlinkTransactionLimit - - var gasPriceInWei *big.Int - if client.Cfg.Network.EIP1559DynamicFees { - gasPriceInWei = estimations.GasFeeCap - } else { - gasPriceInWei = estimations.GasPrice - } - - gasCostPerOperationWei := big.NewInt(1).Mul(big.NewInt(1).SetUint64(gasLimit), gasPriceInWei) - gasCostPerOperationETH := conversions.WeiToEther(gasCostPerOperationWei) - // total Wei needed for all TXs = total value for TX * number of TXs - totalWeiForAllOperations := big.NewInt(1).Mul(gasCostPerOperationWei, bigAmountOfOperations) - totalEthForAllOperations := conversions.WeiToEther(totalWeiForAllOperations) - - l.Debug(). - Int("Number of Operations", amountOfOperations). - Uint64("Gas Limit per Operation", gasLimit). - Str("Value per Operation (ETH)", gasCostPerOperationETH.String()). - Str("Total (ETH)", totalEthForAllOperations.String()). - Msg("Calculated ETH for Chainlink Operations") - - return totalEthForAllOperations, nil -} - -// GetLatestFinalizedBlockHeader returns latest finalised block header for given network (taking into account finality tag/depth) -func GetLatestFinalizedBlockHeader(ctx context.Context, client *seth.Client, network blockchain.EVMNetwork) (*types.Header, error) { - if network.FinalityTag { - return client.Client.HeaderByNumber(ctx, big.NewInt(rpc.FinalizedBlockNumber.Int64())) - } - if network.FinalityDepth == 0 { - return nil, fmt.Errorf("finality depth is 0 and finality tag is not enabled") - } - header, err := client.Client.HeaderByNumber(ctx, nil) - if err != nil { - return nil, err - } - latestBlockNumber := header.Number.Uint64() - finalizedBlockNumber := latestBlockNumber - network.FinalityDepth - return client.Client.HeaderByNumber(ctx, big.NewInt(int64(finalizedBlockNumber))) -} - -// SendLinkFundsToDeploymentAddresses sends LINK token to all addresses, but the root one, from the root address. It uses -// Multicall contract to batch all transfers in a single transaction. It also checks if the funds were transferred correctly. -// It's primary use case is to fund addresses that will be used for Upkeep registration (as that requires LINK balance) during -// Automation/Keeper test setup. -func SendLinkFundsToDeploymentAddresses( - chainClient *seth.Client, - concurrency, - totalUpkeeps, - operationsPerAddress int, - multicallAddress common.Address, - linkAmountPerUpkeep *big.Int, - linkToken contracts.LinkToken, -) error { - var generateCallData = func(receiver common.Address, amount *big.Int) ([]byte, error) { - abi, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return nil, err - } - data, err := abi.Pack("transfer", receiver, amount) - if err != nil { - return nil, err - } - return data, nil - } - - toTransferToMultiCallContract := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(totalUpkeeps+concurrency))) - toTransferPerClient := big.NewInt(0).Mul(linkAmountPerUpkeep, big.NewInt(int64(operationsPerAddress+1))) - err := linkToken.Transfer(multicallAddress.Hex(), toTransferToMultiCallContract) - if err != nil { - return errors.Wrapf(err, "Error transferring LINK to multicall contract") - } - - balance, err := linkToken.BalanceOf(context.Background(), multicallAddress.Hex()) - if err != nil { - return errors.Wrapf(err, "Error getting LINK balance of multicall contract") - } - - if balance.Cmp(toTransferToMultiCallContract) < 0 { - return fmt.Errorf("Incorrect LINK balance of multicall contract. Expected at least: %s. Got: %s", toTransferToMultiCallContract.String(), balance.String()) - } - - // Transfer LINK to ephemeral keys - multiCallData := make([][]byte, 0) - for i := 1; i <= concurrency; i++ { - data, err := generateCallData(chainClient.Addresses[i], toTransferPerClient) - if err != nil { - return errors.Wrapf(err, "Error generating call data for LINK transfer") - } - multiCallData = append(multiCallData, data) - } - - var call []contracts.Call - for _, d := range multiCallData { - data := contracts.Call{Target: common.HexToAddress(linkToken.Address()), AllowFailure: false, CallData: d} - call = append(call, data) - } - - multiCallABI, err := abi.JSON(strings.NewReader(contracts.MultiCallABI)) - if err != nil { - return errors.Wrapf(err, "Error getting Multicall contract ABI") - } - boundContract := bind.NewBoundContract(multicallAddress, multiCallABI, chainClient.Client, chainClient.Client, chainClient.Client) - // call aggregate3 to group all msg call data and send them in a single transaction - _, err = chainClient.Decode(boundContract.Transact(chainClient.NewTXOpts(), "aggregate3", call)) - if err != nil { - return errors.Wrapf(err, "Error calling Multicall contract") - } - - for i := 1; i <= concurrency; i++ { - balance, err := linkToken.BalanceOf(context.Background(), chainClient.Addresses[i].Hex()) - if err != nil { - return errors.Wrapf(err, "Error getting LINK balance of ephemeral key %d", i) - } - if balance.Cmp(toTransferPerClient) < 0 { - return fmt.Errorf("Incorrect LINK balance after transfer. Ephemeral key %d. Expected: %s. Got: %s", i, toTransferPerClient.String(), balance.String()) - } - } - - return nil -} - -var noOpSethConfigFn = func(cfg *seth.Config) error { return nil } - -type SethConfigFunction = func(*seth.Config) error - -// OneEphemeralKeysLiveTestnetCheckFn checks whether there's at least one ephemeral key on a simulated network or at least one static key on a live network, -// and that there are no ephemeral keys on a live network. Root key is excluded from the check. -var OneEphemeralKeysLiveTestnetCheckFn = func(sethCfg *seth.Config) error { - concurrency := sethCfg.GetMaxConcurrency() - - if sethCfg.IsSimulatedNetwork() { - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_EPHEMERAL_KEYS, 0) - } - - return nil - } - - if sethCfg.EphemeralAddrs != nil && int(*sethCfg.EphemeralAddrs) > 0 { - ephMsg := ` - Error: Ephemeral Addresses Detected on Live Network - - Ephemeral addresses are currently set for use on a live network, which is not permitted. The number of ephemeral addresses set is %d. Please make the following update to your TOML configuration file to correct this: - '[Seth] ephemeral_addresses_number = 0' - - Additionally, ensure the following requirements are met to run this test on a live network: - 1. Use more than one private key in your network configuration. - ` - - return errors.New(ephMsg) - } - - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_STATIC_KEYS, len(sethCfg.Network.PrivateKeys)) - } - - return nil -} - -// OneEphemeralKeysLiveTestnetAutoFixFn checks whether there's at least one ephemeral key on a simulated network or at least one static key on a live network, -// and that there are no epehemeral keys on a live network (if ephemeral keys count is different from zero, it will disable them). Root key is excluded from the check. -var OneEphemeralKeysLiveTestnetAutoFixFn = func(sethCfg *seth.Config) error { - concurrency := sethCfg.GetMaxConcurrency() - - if sethCfg.IsSimulatedNetwork() { - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_EPHEMERAL_KEYS, 0) - } - - return nil - } - - if sethCfg.EphemeralAddrs != nil && int(*sethCfg.EphemeralAddrs) > 0 { - var zero int64 = 0 - sethCfg.EphemeralAddrs = &zero - } - - if concurrency < 1 { - return fmt.Errorf(INSUFFICIENT_STATIC_KEYS, len(sethCfg.Network.PrivateKeys)) - } - - return nil -} - -// GetChainClient returns a seth client for the given network after validating the config -func GetChainClient(config ctf_config.SethConfig, network blockchain.EVMNetwork) (*seth.Client, error) { - return GetChainClientWithConfigFunction(config, network, noOpSethConfigFn) -} - -// GetChainClientWithConfigFunction returns a seth client for the given network after validating the config and applying the config function -func GetChainClientWithConfigFunction(config ctf_config.SethConfig, network blockchain.EVMNetwork, configFn SethConfigFunction) (*seth.Client, error) { - readSethCfg := config.GetSethConfig() - if readSethCfg == nil { - return nil, fmt.Errorf("Seth config not found") - } - - sethCfg, err := seth_utils.MergeSethAndEvmNetworkConfigs(network, *readSethCfg) - if err != nil { - return nil, errors.Wrapf(err, "Error merging seth and evm network configs") - } - - err = configFn(&sethCfg) - if err != nil { - return nil, errors.Wrapf(err, "Error applying seth config function") - } - - err = seth_utils.ValidateSethNetworkConfig(sethCfg.Network) - if err != nil { - return nil, errors.Wrapf(err, "Error validating seth network config") - } - - chainClient, err := seth.NewClientWithConfig(&sethCfg) - if err != nil { - return nil, errors.Wrapf(err, "Error creating seth client") - } - - return chainClient, nil -} - -// GenerateUpkeepReport generates a report of performed, successful, reverted and stale upkeeps for a given registry contract based on transaction logs. In case of test failure it can help us -// to triage the issue by providing more context. -func GenerateUpkeepReport(t *testing.T, chainClient *seth.Client, startBlock, endBlock *big.Int, instance contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) (performedUpkeeps, successfulUpkeeps, revertedUpkeeps, staleUpkeeps int, err error) { - registryLogs := []gethtypes.Log{} - l := logging.GetTestLogger(t) - - var ( - blockBatchSize int64 = 100 - logs []gethtypes.Log - timeout = 5 * time.Second - addr = common.HexToAddress(instance.Address()) - queryStartBlock = startBlock - ) - - // Gather logs from the registry in 100 block chunks to avoid read limits - for queryStartBlock.Cmp(endBlock) < 0 { - filterQuery := geth.FilterQuery{ - Addresses: []common.Address{addr}, - FromBlock: queryStartBlock, - ToBlock: big.NewInt(0).Add(queryStartBlock, big.NewInt(blockBatchSize)), - } - - // This RPC call can possibly time out or otherwise die. Failure is not an option, keep retrying to get our stats. - err = fmt.Errorf("initial error") // to ensure our for loop runs at least once - for err != nil { - ctx, cancel := context.WithTimeout(testcontext.Get(t), timeout) - logs, err = chainClient.Client.FilterLogs(ctx, filterQuery) - cancel() - if err != nil { - l.Error(). - Err(err). - Interface("Filter Query", filterQuery). - Str("Timeout", timeout.String()). - Msg("Error getting logs from chain, trying again") - timeout = time.Duration(math.Min(float64(timeout)*2, float64(2*time.Minute))) - continue - } - l.Info(). - Uint64("From Block", queryStartBlock.Uint64()). - Uint64("To Block", filterQuery.ToBlock.Uint64()). - Int("Log Count", len(logs)). - Str("Registry Address", addr.Hex()). - Msg("Collected logs") - queryStartBlock.Add(queryStartBlock, big.NewInt(blockBatchSize)) - registryLogs = append(registryLogs, logs...) - } - } - - var contractABI *abi.ABI - contractABI, err = contracts.GetRegistryContractABI(registryVersion) - if err != nil { - return - } - - for _, allLogs := range registryLogs { - log := allLogs - var eventDetails *abi.Event - eventDetails, err = contractABI.EventByID(log.Topics[0]) - if err != nil { - l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error getting event details for log, report data inaccurate") - break - } - if eventDetails.Name == "UpkeepPerformed" { - performedUpkeeps++ - var parsedLog *contracts.UpkeepPerformedLog - parsedLog, err = instance.ParseUpkeepPerformedLog(&log) - if err != nil { - l.Error().Err(err).Str("Log Hash", log.TxHash.Hex()).Msg("Error parsing upkeep performed log, report data inaccurate") - break - } - if !parsedLog.Success { - revertedUpkeeps++ - } else { - successfulUpkeeps++ - } - } else if eventDetails.Name == "StaleUpkeepReport" { - staleUpkeeps++ - } - } - - return -} - -func GetStalenessReportCleanupFn(t *testing.T, logger zerolog.Logger, chainClient *seth.Client, startBlock uint64, registry contracts.KeeperRegistry, registryVersion ethereum.KeeperRegistryVersion) func() { - return func() { - if t.Failed() { - endBlock, err := chainClient.Client.BlockNumber(context.Background()) - require.NoError(t, err, "Failed to get end block") - - total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, big.NewInt(int64(startBlock)), big.NewInt(int64(endBlock)), registry, registryVersion) - require.NoError(t, err, "Failed to get staleness data") - if stale > 0 || reverted > 0 { - logger.Warn().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") - } else { - logger.Info().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") - } - } - } -} diff --git a/integration-tests/actions/seth/automation_ocr_helpers.go b/integration-tests/actions/seth/automation_ocr_helpers.go deleted file mode 100644 index 160937869a..0000000000 --- a/integration-tests/actions/seth/automation_ocr_helpers.go +++ /dev/null @@ -1,176 +0,0 @@ -package actions_seth - -import ( - "math" - "math/big" - "testing" - - "github.com/pkg/errors" - "github.com/smartcontractkit/seth" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -) - -// DeployAutoOCRRegistryAndRegistrar registry and registrar -func DeployAutoOCRRegistryAndRegistrar( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - registrySettings contracts.KeeperRegistrySettings, - linkToken contracts.LinkToken, -) (contracts.KeeperRegistry, contracts.KeeperRegistrar) { - registry := deployRegistry(t, client, registryVersion, registrySettings, linkToken) - registrar := deployRegistrar(t, client, registryVersion, registry, linkToken) - - return registry, registrar -} - -// DeployConsumers deploys and registers keeper consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. Which means -// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. -func DeployConsumers(t *testing.T, chainClient *seth.Client, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, linkToken contracts.LinkToken, numberOfUpkeeps int, linkFundsForEachUpkeep *big.Int, upkeepGasLimit uint32, isLogTrigger bool, isMercury bool) ([]contracts.KeeperConsumer, []*big.Int) { - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - upkeeps := DeployKeeperConsumers(t, chainClient, numberOfUpkeeps, isLogTrigger, isMercury) - require.Equal(t, numberOfUpkeeps, len(upkeeps), "Number of upkeeps should match") - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts( - t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, isLogTrigger, isMercury, - ) - require.Equal(t, numberOfUpkeeps, len(upkeepIds), "Number of upkeepIds should match") - return upkeeps, upkeepIds -} - -// DeployPerformanceConsumers deploys and registers keeper performance consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkeep will be registered with root key address as the admin. -// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deploys multicall contract and sends link funds to each deployment address. -func DeployPerformanceConsumers( - t *testing.T, - chainClient *seth.Client, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - linkToken contracts.LinkToken, - numberOfUpkeeps int, - linkFundsForEachUpkeep *big.Int, - upkeepGasLimit uint32, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) ([]contracts.KeeperConsumerPerformance, []*big.Int) { - upkeeps := DeployKeeperConsumersPerformance( - t, chainClient, numberOfUpkeeps, blockRange, blockInterval, checkGasToBurn, performGasToBurn, - ) - - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) - return upkeeps, upkeepIds -} - -// DeployPerformDataCheckerConsumers deploys and registers keeper performance data checkers consumers. If ephemeral addresses are enabled, it will deploy and register the consumers from ephemeral addresses, but each upkpeep will be registered with root key address as the admin. -// that functions like setting upkeep configuration, pausing, unpausing, etc. will be done by the root key address. It deployes multicall contract and sends link funds to each deployment address. -func DeployPerformDataCheckerConsumers( - t *testing.T, - chainClient *seth.Client, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - linkToken contracts.LinkToken, - numberOfUpkeeps int, - linkFundsForEachUpkeep *big.Int, - upkeepGasLimit uint32, - expectedData []byte, -) ([]contracts.KeeperPerformDataChecker, []*big.Int) { - upkeeps := DeployPerformDataChecker(t, chainClient, numberOfUpkeeps, expectedData) - - err := DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfUpkeeps, upkeepsAddresses, false, false) - return upkeeps, upkeepIds -} - -// DeployMultiCallAndFundDeploymentAddresses deploys multicall contract and sends link funds to each deployment address -func DeployMultiCallAndFundDeploymentAddresses( - chainClient *seth.Client, - linkToken contracts.LinkToken, - numberOfUpkeeps int, - linkFundsForEachUpkeep *big.Int, -) error { - concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) - if err != nil { - return err - } - - operationsPerAddress := numberOfUpkeeps / concurrency - - multicallAddress, err := contracts.DeployMultiCallContract(chainClient) - if err != nil { - return errors.Wrap(err, "Error deploying multicall contract") - } - - return SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) -} - -func deployRegistrar( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - registry contracts.KeeperRegistry, - linkToken contracts.LinkToken, -) contracts.KeeperRegistrar { - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) - require.NoError(t, err, "Deploying KeeperRegistrar contract shouldn't fail") - return registrar -} - -func deployRegistry( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - registrySettings contracts.KeeperRegistrySettings, - linkToken contracts.LinkToken, -) contracts.KeeperRegistry { - ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - // Deploy the transcoder here, and then set it to the registry - transcoder, err := contracts.DeployUpkeepTranscoder(client) - require.NoError(t, err, "Deploying upkeep transcoder shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - client, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: transcoder.Address(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry contract shouldn't fail") - return registry -} diff --git a/integration-tests/actions/seth/keeper_helpers.go b/integration-tests/actions/seth/keeper_helpers.go deleted file mode 100644 index 5e91d639d4..0000000000 --- a/integration-tests/actions/seth/keeper_helpers.go +++ /dev/null @@ -1,580 +0,0 @@ -package actions_seth - -import ( - "context" - "fmt" - "math" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" - "github.com/pkg/errors" - "github.com/smartcontractkit/seth" - "github.com/stretchr/testify/require" - - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" -) - -var ZeroAddress = common.Address{} - -// DeployKeeperContracts deploys keeper registry and a number of basic upkeep contracts with an update interval of 5. -// It returns the freshly deployed registry, registrar, consumers and the IDs of the upkeeps. -func DeployKeeperContracts( - t *testing.T, - registryVersion ethereum.KeeperRegistryVersion, - registrySettings contracts.KeeperRegistrySettings, - numberOfUpkeeps int, - upkeepGasLimit uint32, - linkToken contracts.LinkToken, - client *seth.Client, - linkFundsForEachUpkeep *big.Int, -) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumer, []*big.Int) { - ef, err := contracts.DeployMockETHLINKFeed(client, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(client, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - // Deploy the transcoder here, and then set it to the registry - transcoder, err := contracts.DeployUpkeepTranscoder(client) - require.NoError(t, err, "Deploying UpkeepTranscoder contract shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - client, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: transcoder.Address(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - - registrar := DeployKeeperRegistrar(t, client, registryVersion, linkToken, registrarSettings, registry) - upkeeps, upkeepIds := DeployConsumers(t, client, registry, registrar, linkToken, numberOfUpkeeps, linkFundsForEachUpkeep, upkeepGasLimit, false, false) - - return registry, registrar, upkeeps, upkeepIds -} - -// DeployPerformanceKeeperContracts deploys a set amount of keeper performance contracts registered to a single registry -func DeployPerformanceKeeperContracts( - t *testing.T, - chainClient *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - numberOfContracts int, - upkeepGasLimit uint32, - linkToken contracts.LinkToken, - registrySettings *contracts.KeeperRegistrySettings, - linkFundsForEachUpkeep *big.Int, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperConsumerPerformance, []*big.Int) { - ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - chainClient, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: ZeroAddress.Hex(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: *registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) - - err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - upkeeps := DeployKeeperConsumersPerformance( - t, chainClient, numberOfContracts, blockRange, blockInterval, checkGasToBurn, performGasToBurn, - ) - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) - - return registry, registrar, upkeeps, upkeepIds -} - -// DeployPerformDataCheckerContracts deploys a set amount of keeper perform data checker contracts registered to a single registry -func DeployPerformDataCheckerContracts( - t *testing.T, - chainClient *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - numberOfContracts int, - upkeepGasLimit uint32, - linkToken contracts.LinkToken, - registrySettings *contracts.KeeperRegistrySettings, - linkFundsForEachUpkeep *big.Int, - expectedData []byte, -) (contracts.KeeperRegistry, contracts.KeeperRegistrar, []contracts.KeeperPerformDataChecker, []*big.Int) { - ef, err := contracts.DeployMockETHLINKFeed(chainClient, big.NewInt(2e18)) - require.NoError(t, err, "Deploying mock ETH-Link feed shouldn't fail") - gf, err := contracts.DeployMockGASFeed(chainClient, big.NewInt(2e11)) - require.NoError(t, err, "Deploying mock gas feed shouldn't fail") - - registry, err := contracts.DeployKeeperRegistry( - chainClient, - &contracts.KeeperRegistryOpts{ - RegistryVersion: registryVersion, - LinkAddr: linkToken.Address(), - ETHFeedAddr: ef.Address(), - GasFeedAddr: gf.Address(), - TranscoderAddr: ZeroAddress.Hex(), - RegistrarAddr: ZeroAddress.Hex(), - Settings: *registrySettings, - }, - ) - require.NoError(t, err, "Deploying KeeperRegistry shouldn't fail") - - // Fund the registry with 1 LINK * amount of KeeperConsumerPerformance contracts - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfContracts)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - registrarSettings := contracts.KeeperRegistrarSettings{ - AutoApproveConfigType: 2, - AutoApproveMaxAllowed: math.MaxUint16, - RegistryAddr: registry.Address(), - MinLinkJuels: big.NewInt(0), - } - - registrar := DeployKeeperRegistrar(t, chainClient, registryVersion, linkToken, registrarSettings, registry) - upkeeps := DeployPerformDataChecker(t, chainClient, numberOfContracts, expectedData) - - err = DeployMultiCallAndFundDeploymentAddresses(chainClient, linkToken, numberOfContracts, linkFundsForEachUpkeep) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - var upkeepsAddresses []string - for _, upkeep := range upkeeps { - upkeepsAddresses = append(upkeepsAddresses, upkeep.Address()) - } - - upkeepIds := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfContracts, upkeepsAddresses, false, false) - - return registry, registrar, upkeeps, upkeepIds -} - -func DeployKeeperRegistrar( - t *testing.T, - client *seth.Client, - registryVersion ethereum.KeeperRegistryVersion, - linkToken contracts.LinkToken, - registrarSettings contracts.KeeperRegistrarSettings, - registry contracts.KeeperRegistry, -) contracts.KeeperRegistrar { - registrar, err := contracts.DeployKeeperRegistrar(client, registryVersion, linkToken.Address(), registrarSettings) - require.NoError(t, err, "Failed waiting for registrar to deploy") - if registryVersion != ethereum.RegistryVersion_2_0 { - err = registry.SetRegistrar(registrar.Address()) - require.NoError(t, err, "Registering the registrar address on the registry shouldn't fail") - } - - return registrar -} - -func RegisterUpkeepContracts(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, isLogTrigger bool, isMercury bool) []*big.Int { - checkData := make([][]byte, 0) - for i := 0; i < numberOfContracts; i++ { - checkData = append(checkData, []byte("0")) - } - return RegisterUpkeepContractsWithCheckData( - t, client, linkToken, linkFunds, upkeepGasLimit, registry, registrar, - numberOfContracts, upkeepAddresses, checkData, isLogTrigger, isMercury) -} - -type upkeepRegistrationResult struct { - upkeepID UpkeepId -} - -func (r upkeepRegistrationResult) GetResult() *big.Int { - return r.upkeepID -} - -type upkeepConfig struct { - address string - data []byte -} - -type UpkeepId = *big.Int - -func RegisterUpkeepContractsWithCheckData(t *testing.T, client *seth.Client, linkToken contracts.LinkToken, linkFunds *big.Int, upkeepGasLimit uint32, registry contracts.KeeperRegistry, registrar contracts.KeeperRegistrar, numberOfContracts int, upkeepAddresses []string, checkData [][]byte, isLogTrigger bool, isMercury bool) []*big.Int { - l := logging.GetTestLogger(t) - - concurrency, err := GetAndAssertCorrectConcurrency(client, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - executor := ctf_concurrency.NewConcurrentExecutor[UpkeepId, upkeepRegistrationResult, upkeepConfig](l) - - configs := make([]upkeepConfig, 0) - for i := 0; i < len(upkeepAddresses); i++ { - configs = append(configs, upkeepConfig{address: upkeepAddresses[i], data: checkData[i]}) - } - - var registerUpkeepFn = func(resultCh chan upkeepRegistrationResult, errorCh chan error, executorNum int, config upkeepConfig) { - uuid := uuid.New().String() - keyNum := executorNum + 1 // key 0 is the root key - - req, err := registrar.EncodeRegisterRequest( - fmt.Sprintf("upkeep_%s", uuid), - []byte("test@mail.com"), - config.address, - upkeepGasLimit, - client.MustGetRootKeyAddress().Hex(), // upkeep Admin - config.data, - linkFunds, - 0, - client.Addresses[keyNum].Hex(), - isLogTrigger, - isMercury, - ) - - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed to encode register request for upkeep at %s", uuid, config.address) - return - } - - balance, err := linkToken.BalanceOf(context.Background(), client.Addresses[keyNum].Hex()) - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s]Failed to get LINK balance of %s", uuid, client.Addresses[keyNum].Hex()) - return - } - - // not stricly necessary, but helps us to avoid an errorless revert if there is not enough LINK - if balance.Cmp(linkFunds) < 0 { - errorCh <- fmt.Errorf("[uuid: %s] Not enough LINK balance for %s. Has: %s. Needs: %s", uuid, client.Addresses[keyNum].Hex(), balance.String(), linkFunds.String()) - return - } - - tx, err := linkToken.TransferAndCallFromKey(registrar.Address(), linkFunds, req, keyNum) - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed to register upkeep at %s", uuid, config.address) - return - } - - receipt, err := client.Client.TransactionReceipt(context.Background(), tx.Hash()) - if err != nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed to get receipt for upkeep at %s and tx hash %s", uuid, config.address, tx.Hash()) - return - } - - var upkeepId *big.Int - for _, rawLog := range receipt.Logs { - parsedUpkeepId, err := registry.ParseUpkeepIdFromRegisteredLog(rawLog) - if err == nil { - upkeepId = parsedUpkeepId - break - } - } - - if upkeepId == nil { - errorCh <- errors.Wrapf(err, "[uuid: %s] Failed find upkeep ID for upkeep at %s in logs of tx with hash %s", uuid, config.address, tx.Hash()) - return - } - - l.Debug(). - Str("TxHash", tx.Hash().String()). - Str("Upkeep ID", upkeepId.String()). - Msg("Found upkeepId in tx hash") - - resultCh <- upkeepRegistrationResult{upkeepID: upkeepId} - } - - upkeepIds, err := executor.Execute(concurrency, configs, registerUpkeepFn) - require.NoError(t, err, "Failed to register upkeeps using executor") - - require.Equal(t, numberOfContracts, len(upkeepIds), "Incorrect number of Keeper Consumer Contracts registered") - l.Info().Msg("Successfully registered all Keeper Consumer Contracts") - - return upkeepIds -} - -type keeperConsumerResult struct { - contract contracts.KeeperConsumer -} - -func (k keeperConsumerResult) GetResult() contracts.KeeperConsumer { - return k.contract -} - -// DeployKeeperConsumers concurrently deploys keeper consumer contracts. It requires at least 1 ephemeral key to be present in Seth config. -func DeployKeeperConsumers(t *testing.T, client *seth.Client, numberOfContracts int, isLogTrigger bool, isMercury bool) []contracts.KeeperConsumer { - l := logging.GetTestLogger(t) - - concurrency, err := GetAndAssertCorrectConcurrency(client, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - executor := ctf_concurrency.NewConcurrentExecutor[contracts.KeeperConsumer, keeperConsumerResult, ctf_concurrency.NoTaskType](l) - - var deployContractFn = func(channel chan keeperConsumerResult, errorCh chan error, executorNum int) { - keyNum := executorNum + 1 // key 0 is the root key - var keeperConsumerInstance contracts.KeeperConsumer - var err error - - if isMercury && isLogTrigger { - // v2.1 only: Log triggered based contract with Mercury enabled - keeperConsumerInstance, err = contracts.DeployAutomationLogTriggeredStreamsLookupUpkeepConsumerFromKey(client, keyNum) - } else if isMercury { - // v2.1 only: Conditional based contract with Mercury enabled - keeperConsumerInstance, err = contracts.DeployAutomationStreamsLookupUpkeepConsumerFromKey(client, keyNum, big.NewInt(1000), big.NewInt(5), false, true, false) // 1000 block test range - } else if isLogTrigger { - // v2.1 only: Log triggered based contract without Mercury - keeperConsumerInstance, err = contracts.DeployAutomationLogTriggerConsumerFromKey(client, keyNum, big.NewInt(1000)) // 1000 block test range - } else { - // v2.0 and v2.1: Conditional based contract without Mercury - keeperConsumerInstance, err = contracts.DeployUpkeepCounterFromKey(client, keyNum, big.NewInt(999999), big.NewInt(5)) - } - - require.NoError(t, err, "Deploying Consumer shouldn't fail") - - channel <- keeperConsumerResult{contract: keeperConsumerInstance} - } - - results, err := executor.ExecuteSimple(concurrency, numberOfContracts, deployContractFn) - require.NoError(t, err, "Failed to deploy keeper consumers") - - // require.Equal(t, 0, len(deplymentErrors), "Error deploying consumer contracts") - require.Equal(t, numberOfContracts, len(results), "Incorrect number of Keeper Consumer Contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return results -} - -// DeployKeeperConsumersPerformance sequentially deploys keeper performance consumer contracts. -func DeployKeeperConsumersPerformance( - t *testing.T, - client *seth.Client, - numberOfContracts int, - blockRange, // How many blocks to run the test for - blockInterval, // Interval of blocks that upkeeps are expected to be performed - checkGasToBurn, // How much gas should be burned on checkUpkeep() calls - performGasToBurn int64, // How much gas should be burned on performUpkeep() calls -) []contracts.KeeperConsumerPerformance { - l := logging.GetTestLogger(t) - upkeeps := make([]contracts.KeeperConsumerPerformance, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer - keeperConsumerInstance, err := contracts.DeployKeeperConsumerPerformance( - client, - big.NewInt(blockRange), - big.NewInt(blockInterval), - big.NewInt(checkGasToBurn), - big.NewInt(performGasToBurn), - ) - require.NoError(t, err, "Deploying KeeperConsumerPerformance instance %d shouldn't fail", contractCount+1) - upkeeps = append(upkeeps, keeperConsumerInstance) - l.Debug(). - Str("Contract Address", keeperConsumerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Performance Contract") - } - - require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of consumers contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeeps -} - -// DeployPerformDataChecker sequentially deploys keeper perform data checker contracts. -func DeployPerformDataChecker( - t *testing.T, - client *seth.Client, - numberOfContracts int, - expectedData []byte, -) []contracts.KeeperPerformDataChecker { - l := logging.GetTestLogger(t) - upkeeps := make([]contracts.KeeperPerformDataChecker, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - performDataCheckerInstance, err := contracts.DeployKeeperPerformDataChecker(client, expectedData) - require.NoError(t, err, "Deploying KeeperPerformDataChecker instance %d shouldn't fail", contractCount+1) - upkeeps = append(upkeeps, performDataCheckerInstance) - l.Debug(). - Str("Contract Address", performDataCheckerInstance.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed PerformDataChecker Contract") - } - require.Equal(t, numberOfContracts, len(upkeeps), "Incorrect number of PerformDataChecker contracts deployed") - l.Info().Msg("Successfully deployed all PerformDataChecker Contracts") - - return upkeeps -} - -// DeployUpkeepCounters sequentially deploys a set amount of upkeep counter contracts. -func DeployUpkeepCounters( - t *testing.T, - client *seth.Client, - numberOfContracts int, - testRange *big.Int, - interval *big.Int, -) []contracts.UpkeepCounter { - l := logging.GetTestLogger(t) - upkeepCounters := make([]contracts.UpkeepCounter, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer - upkeepCounter, err := contracts.DeployUpkeepCounter(client, testRange, interval) - require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) - upkeepCounters = append(upkeepCounters, upkeepCounter) - l.Debug(). - Str("Contract Address", upkeepCounter.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Consumer Contract") - } - require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeepCounters -} - -// DeployUpkeepPerformCounter sequentially deploys a set amount of upkeep perform counter restrictive contracts. -func DeployUpkeepPerformCounterRestrictive( - t *testing.T, - client *seth.Client, - numberOfContracts int, - testRange *big.Int, - averageEligibilityCadence *big.Int, -) []contracts.UpkeepPerformCounterRestrictive { - l := logging.GetTestLogger(t) - upkeepCounters := make([]contracts.UpkeepPerformCounterRestrictive, 0) - - for contractCount := 0; contractCount < numberOfContracts; contractCount++ { - // Deploy consumer - upkeepCounter, err := contracts.DeployUpkeepPerformCounterRestrictive(client, testRange, averageEligibilityCadence) - require.NoError(t, err, "Deploying KeeperConsumer instance %d shouldn't fail", contractCount+1) - upkeepCounters = append(upkeepCounters, upkeepCounter) - l.Debug(). - Str("Contract Address", upkeepCounter.Address()). - Int("Number", contractCount+1). - Int("Out Of", numberOfContracts). - Msg("Deployed Keeper Consumer Contract") - } - require.Equal(t, numberOfContracts, len(upkeepCounters), "Incorrect number of Keeper Consumer contracts deployed") - l.Info().Msg("Successfully deployed all Keeper Consumer Contracts") - - return upkeepCounters -} - -// RegisterNewUpkeeps concurrently registers the given amount of new upkeeps, using the registry and registrar, -// which are passed as parameters. It returns the newly deployed contracts (consumers), as well as their upkeep IDs. -func RegisterNewUpkeeps( - t *testing.T, - chainClient *seth.Client, - linkToken contracts.LinkToken, - registry contracts.KeeperRegistry, - registrar contracts.KeeperRegistrar, - upkeepGasLimit uint32, - numberOfNewUpkeeps int, -) ([]contracts.KeeperConsumer, []*big.Int) { - newlyDeployedUpkeeps := DeployKeeperConsumers(t, chainClient, numberOfNewUpkeeps, false, false) - - var addressesOfNewUpkeeps []string - for _, upkeep := range newlyDeployedUpkeeps { - addressesOfNewUpkeeps = append(addressesOfNewUpkeeps, upkeep.Address()) - } - - concurrency, err := GetAndAssertCorrectConcurrency(chainClient, 1) - require.NoError(t, err, "Insufficient concurrency to execute action") - - operationsPerAddress := numberOfNewUpkeeps / concurrency - - multicallAddress, err := contracts.DeployMultiCallContract(chainClient) - require.NoError(t, err, "Error deploying multicall contract") - - linkFundsForEachUpkeep := big.NewInt(9e18) - - err = SendLinkFundsToDeploymentAddresses(chainClient, concurrency, numberOfNewUpkeeps, operationsPerAddress, multicallAddress, linkFundsForEachUpkeep, linkToken) - require.NoError(t, err, "Sending link funds to deployment addresses shouldn't fail") - - newUpkeepIDs := RegisterUpkeepContracts(t, chainClient, linkToken, linkFundsForEachUpkeep, upkeepGasLimit, registry, registrar, numberOfNewUpkeeps, addressesOfNewUpkeeps, false, false) - - return newlyDeployedUpkeeps, newUpkeepIDs -} - -var INSUFFICIENT_EPHEMERAL_KEYS = ` -Error: Insufficient Ephemeral Addresses for Simulated Network - -To operate on a simulated network, you must configure at least one ephemeral address. Currently, %d ephemeral address(es) are set. Please update your TOML configuration file as follows to meet this requirement: -[Seth] ephemeral_addresses_number = 1 - -This adjustment ensures that your setup is minimaly viable. Although it is highly recommended to use at least 20 ephemeral addresses. -` - -var INSUFFICIENT_STATIC_KEYS = ` -Error: Insufficient Private Keys for Live Network - -To run this test on a live network, you must either: -1. Set at least two private keys in the '[Network.WalletKeys]' section of your TOML configuration file. Example format: - [Network.WalletKeys] - NETWORK_NAME=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] -2. Set at least two private keys in the '[Network.EVMNetworks.NETWORK_NAME] section of your TOML configuration file. Example format: - evm_keys=["PRIVATE_KEY_1", "PRIVATE_KEY_2"] - -Currently, only %d private key/s is/are set. - -Recommended Action: -Distribute your funds across multiple private keys and update your configuration accordingly. Even though 1 private key is sufficient for testing, it is highly recommended to use at least 10 private keys. -` - -// GetAndAssertCorrectConcurrency checks Seth configuration for the number of ephemeral keys or static keys (depending on Seth configuration) and makes sure that -// the number is at least minConcurrency. If the number is less than minConcurrency, it returns an error. The root key is always excluded from the count. -func GetAndAssertCorrectConcurrency(client *seth.Client, minConcurrency int) (int, error) { - concurrency := client.Cfg.GetMaxConcurrency() - - var msg string - if client.Cfg.IsSimulatedNetwork() { - msg = fmt.Sprintf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) - } else { - msg = fmt.Sprintf(INSUFFICIENT_STATIC_KEYS, concurrency) - } - - if concurrency < minConcurrency { - return 0, fmt.Errorf(msg) - } - - return concurrency, nil -} diff --git a/integration-tests/actions/vrf/common/actions.go b/integration-tests/actions/vrf/common/actions.go index d57bdc33b9..db8b44efe9 100644 --- a/integration-tests/actions/vrf/common/actions.go +++ b/integration-tests/actions/vrf/common/actions.go @@ -2,12 +2,19 @@ package common import ( "context" + "encoding/json" "fmt" "math/big" + "os" "sync" "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/go-resty/resty/v2" + "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/rs/zerolog" @@ -16,7 +23,7 @@ import ( ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -65,7 +72,7 @@ func CreateAndFundSendingKeys( return nil, fmt.Errorf("error creating transaction key - response code, err %d", response.StatusCode) } newNativeTokenKeyAddresses = append(newNativeTokenKeyAddresses, newTxKey.Data.Attributes.Address) - _, err = actions_seth.SendFunds(l, client, actions_seth.FundsToSendPayload{ + _, err = actions.SendFunds(l, client, actions.FundsToSendPayload{ ToAddress: common.HexToAddress(newTxKey.Data.Attributes.Address), Amount: conversions.EtherToWei(big.NewFloat(chainlinkNodeFunding)), PrivateKey: client.PrivateKeys[0], @@ -78,7 +85,7 @@ func CreateAndFundSendingKeys( } func SetupBHSNode( - env *test_env.CLClusterTestEnv, + sethClient *seth.Client, config *vrf_common_config.General, numberOfTxKeysToCreate int, chainID *big.Int, @@ -88,11 +95,6 @@ func SetupBHSNode( l zerolog.Logger, bhsNode *VRFNode, ) error { - sethClient, err := env.GetSethClient(chainID.Int64()) - if err != nil { - return err - } - bhsTXKeyAddressStrings, _, err := CreateFundAndGetSendingKeys( l, sethClient, @@ -157,7 +159,7 @@ func CreateBHSJob( } func SetupBHFNode( - env *test_env.CLClusterTestEnv, + sethClient *seth.Client, config *vrf_common_config.General, numberOfTxKeysToCreate int, chainID *big.Int, @@ -168,10 +170,6 @@ func SetupBHFNode( l zerolog.Logger, bhfNode *VRFNode, ) error { - sethClient, err := env.GetSethClient(chainID.Int64()) - if err != nil { - return err - } bhfTXKeyAddressStrings, _, err := CreateFundAndGetSendingKeys( l, sethClient, @@ -336,7 +334,7 @@ func FundNodesIfNeeded(ctx context.Context, existingEnvConfig *vrf_common_config Str("Funding Amount in wei", fundingToSendWei.String()). Str("Funding Amount in ETH", conversions.WeiToEther(fundingToSendWei).String()). Msg("Funding Node's Sending Key") - _, err := actions_seth.SendFunds(l, client, actions_seth.FundsToSendPayload{ + _, err := actions.SendFunds(l, client, actions.FundsToSendPayload{ ToAddress: common.HexToAddress(sendingKey), Amount: fundingToSendWei, PrivateKey: client.PrivateKeys[0], @@ -353,19 +351,129 @@ func FundNodesIfNeeded(ctx context.Context, existingEnvConfig *vrf_common_config return nil } -func BuildNewCLEnvForVRF(t *testing.T, envConfig VRFEnvConfig, newEnvConfig NewEnvConfig, network ctf_test_env.EthereumNetwork) (*test_env.CLClusterTestEnv, error) { +func BuildNewCLEnvForVRF(l zerolog.Logger, t *testing.T, envConfig VRFEnvConfig, newEnvConfig NewEnvConfig, network ctf_test_env.EthereumNetwork) (*test_env.CLClusterTestEnv, *seth.Client, error) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&envConfig.TestConfig). WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithCLNodes(len(newEnvConfig.NodesToCreate)). - WithFunding(big.NewFloat(*envConfig.TestConfig.Common.ChainlinkNodeFunding)). WithChainlinkNodeLogScanner(newEnvConfig.ChainlinkNodeLogScannerSettings). WithCustomCleanup(envConfig.CleanupFn). - WithSeth(). Build() if err != nil { - return nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + return nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + } + + evmNetwork, err := env.GetFirstEvmNetwork() + if err != nil { + return nil, nil, fmt.Errorf("%s, err: %w", "error getting first evm network", err) + } + sethClient, err := seth_utils.GetChainClient(envConfig.TestConfig, *evmNetwork) + if err != nil { + return nil, nil, fmt.Errorf("%s, err: %w", "error getting seth client", err) + } + + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*envConfig.TestConfig.Common.ChainlinkNodeFunding)) + if err != nil { + return nil, nil, fmt.Errorf("%s, err: %w", "failed to fund the nodes", err) + } + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + + return env, sethClient, nil +} + +func GetRPCUrl(env *test_env.CLClusterTestEnv, chainID int64) (string, error) { + provider, err := env.GetRpcProvider(chainID) + if err != nil { + return "", err + } + return provider.PublicHttpUrls()[0], nil +} + +// RPCRawClient +// created separate client since method evmClient.RawJsonRPCCall fails on "invalid argument 0: json: cannot unmarshal non-string into Go value of type hexutil.Uint64" +type RPCRawClient struct { + resty *resty.Client +} + +func NewRPCRawClient(url string) *RPCRawClient { + isDebug := os.Getenv("DEBUG_RESTY") == "true" + restyClient := resty.New().SetDebug(isDebug).SetBaseURL(url) + return &RPCRawClient{ + resty: restyClient, } - return env, nil +} + +func (g *RPCRawClient) SetHeadForSimulatedChain(setHeadToBlockNumber uint64) (JsonRPCResponse, error) { + var responseObject JsonRPCResponse + postBody, _ := json.Marshal(map[string]any{ + "jsonrpc": "2.0", + "id": 1, + "method": "debug_setHead", + "params": []string{hexutil.EncodeUint64(setHeadToBlockNumber)}, + }) + resp, err := g.resty.R(). + SetHeader("Content-Type", "application/json"). + SetBody(postBody). + SetResult(&responseObject). + Post("") + + if err != nil { + return JsonRPCResponse{}, fmt.Errorf("error making API request: %w", err) + } + statusCode := resp.StatusCode() + if statusCode != 200 && statusCode != 201 { + return JsonRPCResponse{}, fmt.Errorf("error invoking debug_setHead method, received unexpected status code %d: %s", statusCode, resp.String()) + } + if responseObject.Error != "" { + return JsonRPCResponse{}, fmt.Errorf("received non-empty error field: %v", responseObject.Error) + } + return responseObject, nil +} + +type JsonRPCResponse struct { + Version string `json:"jsonrpc"` + Id int `json:"id"` + Result string `json:"result,omitempty"` + Error string `json:"error,omitempty"` +} + +// todo - move to CTF +func RewindSimulatedChainToBlockNumber( + ctx context.Context, + client *seth.Client, + rpcURL string, + rewindChainToBlockNumber uint64, + l zerolog.Logger, +) (uint64, error) { + latestBlockNumberBeforeReorg, err := client.Client.BlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Str("RPC URL", rpcURL). + Uint64("Latest Block Number before Reorg", latestBlockNumberBeforeReorg). + Uint64("Rewind Chain to Block Number", rewindChainToBlockNumber). + Msg("Performing Reorg on chain by rewinding chain to specific block number") + + _, err = NewRPCRawClient(rpcURL).SetHeadForSimulatedChain(rewindChainToBlockNumber) + + if err != nil { + return 0, fmt.Errorf("error making reorg: %w", err) + } + + latestBlockNumberAfterReorg, err := client.Client.BlockNumber(ctx) + if err != nil { + return 0, fmt.Errorf("error getting latest block number: %w", err) + } + + l.Info(). + Uint64("Block Number", latestBlockNumberAfterReorg). + Msg("Latest Block Number after Reorg") + return latestBlockNumberAfterReorg, nil } diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 92da7b9f86..4ea49a9b72 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -18,7 +18,6 @@ import ( vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -27,18 +26,12 @@ import ( ) func DeployVRFV2Contracts( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, linkTokenContract contracts.LinkToken, linkEthFeedContract contracts.VRFMockETHLINKFeed, useVRFOwner bool, useTestCoordinator bool, ) (*vrfcommon.VRFContracts, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, err - } - bhs, err := contracts.DeployBlockhashStore(sethClient) if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployBlockHashStore, err) @@ -95,10 +88,10 @@ func DeployVRFV2Contracts( }, nil } -func DeployVRFV2Consumers(client *seth.Client, coordinatorAddress string, consumerContractsAmount int) ([]contracts.VRFv2LoadTestConsumer, error) { +func DeployVRFV2Consumers(sethClient *seth.Client, coordinatorAddress string, consumerContractsAmount int) ([]contracts.VRFv2LoadTestConsumer, error) { var consumers []contracts.VRFv2LoadTestConsumer for i := 1; i <= consumerContractsAmount; i++ { - loadTestConsumer, err := contracts.DeployVRFv2LoadTestConsumer(client, coordinatorAddress) + loadTestConsumer, err := contracts.DeployVRFv2LoadTestConsumer(sethClient, coordinatorAddress) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err) } @@ -107,10 +100,10 @@ func DeployVRFV2Consumers(client *seth.Client, coordinatorAddress string, consum return consumers, nil } -func DeployVRFV2WrapperConsumers(client *seth.Client, linkTokenAddress string, vrfV2Wrapper contracts.VRFV2Wrapper, consumerContractsAmount int) ([]contracts.VRFv2WrapperLoadTestConsumer, error) { +func DeployVRFV2WrapperConsumers(sethClient *seth.Client, linkTokenAddress string, vrfV2Wrapper contracts.VRFV2Wrapper, consumerContractsAmount int) ([]contracts.VRFv2WrapperLoadTestConsumer, error) { var consumers []contracts.VRFv2WrapperLoadTestConsumer for i := 1; i <= consumerContractsAmount; i++ { - loadTestConsumer, err := contracts.DeployVRFV2WrapperLoadTestConsumer(client, linkTokenAddress, vrfV2Wrapper.Address()) + loadTestConsumer, err := contracts.DeployVRFV2WrapperLoadTestConsumer(sethClient, linkTokenAddress, vrfV2Wrapper.Address()) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrAdvancedConsumer, err) } @@ -120,17 +113,17 @@ func DeployVRFV2WrapperConsumers(client *seth.Client, linkTokenAddress string, v } func DeployVRFV2DirectFundingContracts( - client *seth.Client, + sethClient *seth.Client, linkTokenAddress string, linkEthFeedAddress string, coordinator contracts.VRFCoordinatorV2, consumerContractsAmount int, ) (*VRFV2WrapperContracts, error) { - vrfv2Wrapper, err := contracts.DeployVRFV2Wrapper(client, linkTokenAddress, linkEthFeedAddress, coordinator.Address()) + vrfv2Wrapper, err := contracts.DeployVRFV2Wrapper(sethClient, linkTokenAddress, linkEthFeedAddress, coordinator.Address()) if err != nil { return nil, fmt.Errorf("%s, err %w", ErrDeployVRFV2Wrapper, err) } - consumers, err := DeployVRFV2WrapperConsumers(client, linkTokenAddress, vrfv2Wrapper, consumerContractsAmount) + consumers, err := DeployVRFV2WrapperConsumers(sethClient, linkTokenAddress, vrfv2Wrapper, consumerContractsAmount) if err != nil { return nil, err } @@ -157,8 +150,7 @@ func VRFV2RegisterProvingKey( } func SetupVRFV2Contracts( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.VRFMockETHLINKFeed, useVRFOwner bool, @@ -168,8 +160,7 @@ func SetupVRFV2Contracts( ) (*vrfcommon.VRFContracts, error) { l.Info().Msg("Deploying VRFV2 contracts") vrfContracts, err := DeployVRFV2Contracts( - env, - chainID, + sethClient, linkToken, mockNativeLINKFeed, useVRFOwner, @@ -634,8 +625,7 @@ func SetupVRFOwnerContractIfNeeded(useVRFOwner bool, vrfContracts *vrfcommon.VRF } func SetupNewConsumersAndSubs( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2, testConfig tc.TestConfig, linkToken contracts.LinkToken, @@ -643,10 +633,6 @@ func SetupNewConsumersAndSubs( numberOfSubToCreate int, l zerolog.Logger, ) ([]contracts.VRFv2LoadTestConsumer, []uint64, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } consumers, err := DeployVRFV2Consumers(sethClient, coordinator.Address(), numberOfConsumerContractsToDeployAndAddToSub) if err != nil { return nil, nil, fmt.Errorf("err: %w", err) diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index 546508842d..c13aed807a 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -6,6 +6,10 @@ import ( "math/big" "testing" + "github.com/smartcontractkit/seth" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "golang.org/x/sync/errgroup" @@ -75,6 +79,7 @@ func CreateVRFV2Job( // SetupVRFV2Environment will create specified number of subscriptions and add the same conumer/s to each of them func SetupVRFV2Environment( ctx context.Context, + sethClient *seth.Client, env *test_env.CLClusterTestEnv, chainID int64, nodesToCreate []vrfcommon.VRFNodeType, @@ -90,8 +95,7 @@ func SetupVRFV2Environment( l.Info().Msg("Starting VRFV2 environment setup") configGeneral := vrfv2TestConfig.GetVRFv2Config().General vrfContracts, err := SetupVRFV2Contracts( - env, - chainID, + sethClient, linkToken, mockNativeLINKFeed, useVRFOwner, @@ -122,11 +126,6 @@ func SetupVRFV2Environment( return nil, nil, nil, fmt.Errorf("%s, err %w", vrfcommon.ErrCreatingProvingKeyHash, err) } - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, nil, err - } - vrfTXKeyAddressStrings, vrfTXKeyAddresses, err := vrfcommon.CreateFundAndGetSendingKeys( l, sethClient, @@ -160,7 +159,7 @@ func SetupVRFV2Environment( if bhsNode, exists := nodeTypeToNodeMap[vrfcommon.BHS]; exists { g.Go(func() error { err := vrfcommon.SetupBHSNode( - env, + sethClient, configGeneral.General, numberOfTxKeysToCreate, big.NewInt(chainID), @@ -236,8 +235,7 @@ func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, vrfv2Conf func SetupVRFV2WrapperEnvironment( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, vrfv2TestConfig tc.VRFv2TestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.VRFMockETHLINKFeed, @@ -245,11 +243,6 @@ func SetupVRFV2WrapperEnvironment( keyHash [32]byte, wrapperConsumerContractsAmount int, ) (*VRFV2WrapperContracts, *uint64, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } - // Deploy VRF v2 direct funding contracts wrapperContracts, err := DeployVRFV2DirectFundingContracts( sethClient, @@ -306,26 +299,28 @@ func SetupVRFV2Universe( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { var ( env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client err error ) if *envConfig.TestConfig.VRFv2.General.UseExistingEnv { - vrfContracts, vrfKey, env, err = SetupVRFV2ForExistingEnv(t, envConfig, l) + vrfContracts, vrfKey, env, sethClient, err = SetupVRFV2ForExistingEnv(t, envConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for Existing env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for Existing env", err) } } else { - vrfContracts, vrfKey, env, nodeTypeToNodeMap, err = SetupVRFV2ForNewEnv(ctx, t, envConfig, newEnvConfig, l) + vrfContracts, vrfKey, env, nodeTypeToNodeMap, sethClient, err = SetupVRFV2ForNewEnv(ctx, t, envConfig, newEnvConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for New env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 for New env", err) } } - return env, vrfContracts, vrfKey, nodeTypeToNodeMap, nil + + return env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, nil } func SetupVRFV2ForNewEnv( @@ -334,29 +329,26 @@ func SetupVRFV2ForNewEnv( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { network, err := actions.EthereumNetworkConfigFromConfig(l, &envConfig.TestConfig) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2", err) } - env, err := vrfcommon.BuildNewCLEnvForVRF(t, envConfig, newEnvConfig, network) + env, sethClient, err := vrfcommon.BuildNewCLEnvForVRF(l, t, envConfig, newEnvConfig, network) if err != nil { - return nil, nil, nil, nil, err - } - sethClient, err := env.GetSethClientForSelectedNetwork() - if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } mockETHLinkFeed, err := contracts.DeployVRFMockETHLINKFeed(sethClient, big.NewInt(*envConfig.TestConfig.VRFv2.General.LinkNativeFeedResponse)) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) } linkToken, err := contracts.DeployLinkTokenContract(l, sethClient) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) } vrfContracts, vrfKey, nodeTypeToNode, err := SetupVRFV2Environment( ctx, + sethClient, env, envConfig.ChainID, newEnvConfig.NodesToCreate, @@ -371,50 +363,50 @@ func SetupVRFV2ForNewEnv( l, ) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2 env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2 env", err) } - return vrfContracts, vrfKey, env, nodeTypeToNode, nil + + return vrfContracts, vrfKey, env, nodeTypeToNode, sethClient, nil } -func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, error) { +func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, *seth.Client, error) { commonExistingEnvConfig := envConfig.TestConfig.VRFv2.ExistingEnvConfig.ExistingEnvConfig env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&envConfig.TestConfig). WithCustomCleanup(envConfig.CleanupFn). - WithSeth(). Build() if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) } - client, err := env.GetSethClientForSelectedNetwork() + evmNetwork, err := env.GetFirstEvmNetwork() if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err } - coordinator, err := contracts.LoadVRFCoordinatorV2(client, *commonExistingEnvConfig.ConsumerAddress) + sethClient, err := seth_utils.GetChainClient(envConfig.TestConfig, *evmNetwork) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2", err) + return nil, nil, nil, nil, err } - linkAddr := common.HexToAddress(*commonExistingEnvConfig.LinkAddress) - linkToken, err := contracts.LoadLinkTokenContract(l, client, linkAddr) + coordinator, err := contracts.LoadVRFCoordinatorV2(sethClient, *commonExistingEnvConfig.ConsumerAddress) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2", err) } - sethClient, err := env.GetSethClient(envConfig.ChainID) + linkAddr := common.HexToAddress(*commonExistingEnvConfig.LinkAddress) + linkToken, err := contracts.LoadLinkTokenContract(l, sethClient, linkAddr) if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) } err = vrfcommon.FundNodesIfNeeded(testcontext.Get(t), commonExistingEnvConfig, sethClient, l) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStoreAddress, err := coordinator.GetBlockHashStoreAddress(testcontext.Get(t)) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStore, err := contracts.LoadBlockHashStore(sethClient, blockHashStoreAddress.String()) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) } vrfContracts := &vrfcommon.VRFContracts{ CoordinatorV2: coordinator, @@ -427,12 +419,11 @@ func SetupVRFV2ForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l EncodedProvingKey: [2]*big.Int{}, KeyHash: common.HexToHash(*commonExistingEnvConfig.KeyHash), } - return vrfContracts, vrfKey, env, nil + return vrfContracts, vrfKey, env, sethClient, nil } func SetupSubsAndConsumersForExistingEnv( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2, linkToken contracts.LinkToken, numberOfConsumerContractsToDeployAndAddToSub int, @@ -449,8 +440,7 @@ func SetupSubsAndConsumersForExistingEnv( commonExistingEnvConfig := testConfig.VRFv2.ExistingEnvConfig.ExistingEnvConfig if *commonExistingEnvConfig.CreateFundSubsAndAddConsumers { consumers, subIDs, err = SetupNewConsumersAndSubs( - env, - chainID, + sethClient, coordinator, testConfig, linkToken, @@ -462,12 +452,8 @@ func SetupSubsAndConsumersForExistingEnv( return nil, nil, fmt.Errorf("err: %w", err) } } else { - client, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } addr := common.HexToAddress(*commonExistingEnvConfig.ConsumerAddress) - consumer, err := contracts.LoadVRFv2LoadTestConsumer(client, addr) + consumer, err := contracts.LoadVRFv2LoadTestConsumer(sethClient, addr) if err != nil { return nil, nil, fmt.Errorf("err: %w", err) } @@ -476,8 +462,7 @@ func SetupSubsAndConsumersForExistingEnv( } } else { consumers, subIDs, err = SetupNewConsumersAndSubs( - env, - chainID, + sethClient, coordinator, testConfig, linkToken, diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index ed6139c4f1..8d06678690 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -18,7 +18,6 @@ import ( vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -121,8 +120,7 @@ func FundVRFCoordinatorV2_5Subscription( func CreateFundSubsAndAddConsumers( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, subscriptionFundingAmountNative *big.Float, subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, @@ -132,8 +130,7 @@ func CreateFundSubsAndAddConsumers( ) ([]*big.Int, error) { subIDs, err := CreateSubsAndFund( ctx, - env, - chainID, + sethClient, subscriptionFundingAmountNative, subscriptionFundingAmountLink, linkToken, @@ -160,15 +157,14 @@ func CreateFundSubsAndAddConsumers( func CreateSubsAndFund( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, subscriptionFundingAmountNative *big.Float, subscriptionFundingAmountLink *big.Float, linkToken contracts.LinkToken, coordinator contracts.VRFCoordinatorV2_5, subAmountToCreate int, ) ([]*big.Int, error) { - subs, err := CreateSubs(ctx, env, chainID, coordinator, subAmountToCreate) + subs, err := CreateSubs(ctx, sethClient, coordinator, subAmountToCreate) if err != nil { return nil, err } @@ -187,15 +183,14 @@ func CreateSubsAndFund( func CreateSubs( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5, subAmountToCreate int, ) ([]*big.Int, error) { var subIDArr []*big.Int for i := 0; i < subAmountToCreate; i++ { - subID, err := CreateSubAndFindSubID(ctx, env, chainID, coordinator) + subID, err := CreateSubAndFindSubID(ctx, sethClient, coordinator) if err != nil { return nil, err } @@ -219,15 +214,11 @@ func AddConsumersToSubs( return nil } -func CreateSubAndFindSubID(ctx context.Context, env *test_env.CLClusterTestEnv, chainID int64, coordinator contracts.VRFCoordinatorV2_5) (*big.Int, error) { +func CreateSubAndFindSubID(ctx context.Context, sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5) (*big.Int, error) { tx, err := coordinator.CreateSubscription() if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrCreateVRFSubscription, err) } - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, err - } receipt, err := sethClient.Client.TransactionReceipt(ctx, tx.Hash()) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrWaitTXsComplete, err) @@ -508,18 +499,13 @@ func DeployVRFV2PlusWrapperConsumers(client *seth.Client, vrfV2PlusWrapper contr } func SetupVRFV2PlusContracts( - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.VRFMockETHLINKFeed, configGeneral *vrfv2plus_config.General, l zerolog.Logger, ) (*vrfcommon.VRFContracts, error) { l.Info().Msg("Deploying VRFV2 Plus contracts") - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, err - } vrfContracts, err := DeployVRFV2_5Contracts(sethClient) if err != nil { return nil, fmt.Errorf(vrfcommon.ErrGenericFormat, ErrDeployVRFV2_5Contracts, err) @@ -554,8 +540,7 @@ func SetupVRFV2PlusContracts( func SetupNewConsumersAndSubs( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5, testConfig tc.TestConfig, linkToken contracts.LinkToken, @@ -563,10 +548,6 @@ func SetupNewConsumersAndSubs( numberOfSubToCreate int, l zerolog.Logger, ) ([]contracts.VRFv2PlusLoadTestConsumer, []*big.Int, error) { - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } consumers, err := DeployVRFV2PlusConsumers(sethClient, coordinator, consumerContractsAmount) if err != nil { return nil, nil, fmt.Errorf("err: %w", err) @@ -577,8 +558,7 @@ func SetupNewConsumersAndSubs( Msg("Creating and funding subscriptions, deploying and adding consumers to subs") subIDs, err := CreateFundSubsAndAddConsumers( ctx, - env, - chainID, + sethClient, big.NewFloat(*testConfig.VRFv2Plus.General.SubscriptionFundingAmountNative), big.NewFloat(*testConfig.VRFv2Plus.General.SubscriptionFundingAmountLink), linkToken, diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 16fe1b9427..63890c3b9d 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -6,6 +6,10 @@ import ( "math/big" "testing" + "github.com/smartcontractkit/seth" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/shopspring/decimal" "golang.org/x/sync/errgroup" @@ -15,13 +19,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -75,6 +78,7 @@ func CreateVRFV2PlusJob( // SetupVRFV2_5Environment will create specified number of subscriptions and add the same conumer/s to each of them func SetupVRFV2_5Environment( ctx context.Context, + sethClient *seth.Client, env *test_env.CLClusterTestEnv, chainID int64, nodesToCreate []vrfcommon.VRFNodeType, @@ -86,9 +90,9 @@ func SetupVRFV2_5Environment( ) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { l.Info().Msg("Starting VRFV2 Plus environment setup") configGeneral := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General + vrfContracts, err := SetupVRFV2PlusContracts( - env, - chainID, + sethClient, linkToken, mockNativeLINKFeed, configGeneral, @@ -116,11 +120,6 @@ func SetupVRFV2_5Environment( return nil, nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrCreatingProvingKeyHash, err) } - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, nil, err - } - vrfTXKeyAddressStrings, _, err := vrfcommon.CreateFundAndGetSendingKeys( l, sethClient, @@ -149,7 +148,7 @@ func SetupVRFV2_5Environment( if bhsNode, exists := nodeTypeToNodeMap[vrfcommon.BHS]; exists { g.Go(func() error { err := vrfcommon.SetupBHSNode( - env, + sethClient, configGeneral.General, numberOfTxKeysToCreate, big.NewInt(chainID), @@ -169,7 +168,7 @@ func SetupVRFV2_5Environment( if bhfNode, exists := nodeTypeToNodeMap[vrfcommon.BHF]; exists { g.Go(func() error { err := vrfcommon.SetupBHFNode( - env, + sethClient, configGeneral.General, numberOfTxKeysToCreate, big.NewInt(chainID), @@ -247,8 +246,7 @@ func setupVRFNode(contracts *vrfcommon.VRFContracts, chainID *big.Int, config *v func SetupVRFV2PlusWrapperEnvironment( ctx context.Context, l zerolog.Logger, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, vrfv2PlusTestConfig types.VRFv2PlusTestConfig, linkToken contracts.LinkToken, mockNativeLINKFeed contracts.MockETHLINKFeed, @@ -257,18 +255,12 @@ func SetupVRFV2PlusWrapperEnvironment( wrapperConsumerContractsAmount int, ) (*VRFV2PlusWrapperContracts, *big.Int, error) { // external EOA has to create a subscription for the wrapper first - wrapperSubId, err := CreateSubAndFindSubID(ctx, env, chainID, coordinator) + wrapperSubId, err := CreateSubAndFindSubID(ctx, sethClient, coordinator) if err != nil { return nil, nil, err } vrfv2PlusConfig := vrfv2PlusTestConfig.GetVRFv2PlusConfig().General - - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } - wrapperContracts, err := DeployVRFV2PlusDirectFundingContracts( sethClient, linkToken.Address(), @@ -332,7 +324,7 @@ func SetupVRFV2PlusWrapperEnvironment( } //fund consumer with Eth (native token) - _, err = actions_seth.SendFunds(l, sethClient, actions_seth.FundsToSendPayload{ + _, err = actions.SendFunds(l, sethClient, actions.FundsToSendPayload{ ToAddress: common.HexToAddress(wrapperContracts.LoadTestConsumers[0].Address()), Amount: conversions.EtherToWei(big.NewFloat(*vrfv2PlusConfig.WrapperConsumerFundingAmountNativeToken)), PrivateKey: sethClient.PrivateKeys[0], @@ -359,26 +351,28 @@ func SetupVRFV2PlusUniverse( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*test_env.CLClusterTestEnv, *vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { var ( env *test_env.CLClusterTestEnv vrfContracts *vrfcommon.VRFContracts vrfKey *vrfcommon.VRFKeyData nodeTypeToNode map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client err error ) if *envConfig.TestConfig.VRFv2Plus.General.UseExistingEnv { - vrfContracts, vrfKey, env, err = SetupVRFV2PlusForExistingEnv(t, envConfig, l) + vrfContracts, vrfKey, env, sethClient, err = SetupVRFV2PlusForExistingEnv(t, envConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for Existing env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for Existing env", err) } } else { - vrfContracts, vrfKey, env, nodeTypeToNode, err = SetupVRFV2PlusForNewEnv(ctx, t, envConfig, newEnvConfig, l) + vrfContracts, vrfKey, env, nodeTypeToNode, sethClient, err = SetupVRFV2PlusForNewEnv(ctx, t, envConfig, newEnvConfig, l) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for New env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error setting up VRF V2 Plus for New env", err) } } - return env, vrfContracts, vrfKey, nodeTypeToNode, nil + + return env, vrfContracts, vrfKey, nodeTypeToNode, sethClient, nil } func SetupVRFV2PlusForNewEnv( @@ -387,29 +381,26 @@ func SetupVRFV2PlusForNewEnv( envConfig vrfcommon.VRFEnvConfig, newEnvConfig vrfcommon.NewEnvConfig, l zerolog.Logger, -) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, error) { +) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode, *seth.Client, error) { network, err := actions.EthereumNetworkConfigFromConfig(l, &envConfig.TestConfig) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2Plus", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "Error building ethereum network config for V2Plus", err) } - env, err := vrfcommon.BuildNewCLEnvForVRF(t, envConfig, newEnvConfig, network) + env, sethClient, err := vrfcommon.BuildNewCLEnvForVRF(l, t, envConfig, newEnvConfig, network) if err != nil { - return nil, nil, nil, nil, err - } - sethClient, err := env.GetSethClient(envConfig.ChainID) - if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } mockETHLinkFeed, err := contracts.DeployVRFMockETHLINKFeed(sethClient, big.NewInt(*envConfig.TestConfig.VRFv2Plus.General.LinkNativeFeedResponse)) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying mock ETH/LINK feed", err) } linkToken, err := contracts.DeployLinkTokenContract(l, sethClient) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error deploying LINK contract", err) } vrfContracts, vrfKey, nodeTypeToNode, err := SetupVRFV2_5Environment( ctx, + sethClient, env, envConfig.ChainID, newEnvConfig.NodesToCreate, @@ -420,45 +411,49 @@ func SetupVRFV2PlusForNewEnv( l, ) if err != nil { - return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2_5 env", err) + return nil, nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error setting up VRF v2_5 env", err) } - return vrfContracts, vrfKey, env, nodeTypeToNode, nil + + return vrfContracts, vrfKey, env, nodeTypeToNode, sethClient, nil } -func SetupVRFV2PlusForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, error) { +func SetupVRFV2PlusForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig, l zerolog.Logger) (*vrfcommon.VRFContracts, *vrfcommon.VRFKeyData, *test_env.CLClusterTestEnv, *seth.Client, error) { commonExistingEnvConfig := envConfig.TestConfig.VRFv2Plus.ExistingEnvConfig.ExistingEnvConfig env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&envConfig.TestConfig). WithCustomCleanup(envConfig.CleanupFn). - WithSeth(). Build() if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error creating test env", err) } - sethClient, err := env.GetSethClient(envConfig.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err + } + sethClient, err := seth_utils.GetChainClient(envConfig.TestConfig, *evmNetwork) + if err != nil { + return nil, nil, nil, nil, err } coordinator, err := contracts.LoadVRFCoordinatorV2_5(sethClient, *commonExistingEnvConfig.CoordinatorAddress) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2_5", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading VRFCoordinator2_5", err) } linkToken, err := contracts.LoadLinkTokenContract(l, sethClient, common.HexToAddress(*commonExistingEnvConfig.LinkAddress)) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading LinkToken", err) } err = vrfcommon.FundNodesIfNeeded(testcontext.Get(t), commonExistingEnvConfig, sethClient, l) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStoreAddress, err := coordinator.GetBlockHashStoreAddress(testcontext.Get(t)) if err != nil { - return nil, nil, nil, fmt.Errorf("err: %w", err) + return nil, nil, nil, nil, fmt.Errorf("err: %w", err) } blockHashStore, err := contracts.LoadBlockHashStore(sethClient, blockHashStoreAddress.String()) if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) + return nil, nil, nil, nil, fmt.Errorf("%s, err: %w", "error loading BlockHashStore", err) } vrfContracts := &vrfcommon.VRFContracts{ CoordinatorV2Plus: coordinator, @@ -471,13 +466,12 @@ func SetupVRFV2PlusForExistingEnv(t *testing.T, envConfig vrfcommon.VRFEnvConfig EncodedProvingKey: [2]*big.Int{}, KeyHash: common.HexToHash(*commonExistingEnvConfig.KeyHash), } - return vrfContracts, vrfKey, env, nil + return vrfContracts, vrfKey, env, sethClient, nil } func SetupSubsAndConsumersForExistingEnv( ctx context.Context, - env *test_env.CLClusterTestEnv, - chainID int64, + sethClient *seth.Client, coordinator contracts.VRFCoordinatorV2_5, linkToken contracts.LinkToken, numberOfConsumerContractsToDeployAndAddToSub int, @@ -490,17 +484,12 @@ func SetupSubsAndConsumersForExistingEnv( consumers []contracts.VRFv2PlusLoadTestConsumer err error ) - sethClient, err := env.GetSethClient(chainID) - if err != nil { - return nil, nil, err - } if *testConfig.VRFv2Plus.General.UseExistingEnv { commonExistingEnvConfig := testConfig.VRFv2Plus.ExistingEnvConfig.ExistingEnvConfig if *commonExistingEnvConfig.CreateFundSubsAndAddConsumers { consumers, subIDs, err = SetupNewConsumersAndSubs( ctx, - env, - chainID, + sethClient, coordinator, testConfig, linkToken, @@ -527,8 +516,7 @@ func SetupSubsAndConsumersForExistingEnv( } else { consumers, subIDs, err = SetupNewConsumersAndSubs( ctx, - env, - chainID, + sethClient, coordinator, testConfig, linkToken, diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 2c3aa2fdd1..2559ddd495 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -20,7 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -144,7 +144,7 @@ func TestAutomationBenchmark(t *testing.T) { l.Info().Str("Namespace", testEnvironment.Cfg.Namespace).Msg("Connected to Keepers Benchmark Environment") testNetwork := seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, benchmarkNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(&config, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetAutoFixFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(&config, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetAutoFixFn) require.NoError(t, err, "Error getting Seth client") registryVersions := addRegistry(&config) @@ -192,7 +192,7 @@ func TestAutomationBenchmark(t *testing.T) { }, ) t.Cleanup(func() { - if err = actions_seth.TeardownRemoteSuite(keeperBenchmarkTest.TearDownVals(t)); err != nil { + if err = actions.TeardownRemoteSuite(keeperBenchmarkTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error when tearing down remote suite") } }) diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index fcbf8f5a47..a6267138d2 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -245,24 +244,24 @@ func TestAutomationChaos(t *testing.T) { network = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, network, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(&config, network, actions_seth.OneEphemeralKeysLiveTestnetAutoFixFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(&config, network, seth_utils.OneEphemeralKeysLiveTestnetAutoFixFn) require.NoError(t, err, "Error creating seth client") // Register cleanup for any test t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) require.NoError(t, err, "Error tearing down environment") }) - txCost, err := actions_seth.EstimateCostForChainlinkOperations(l, chainClient, network, 1000) + txCost, err := actions.EstimateCostForChainlinkOperations(l, chainClient, network, 1000) require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), txCost) + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), txCost) require.NoError(t, err, "Error funding Chainlink nodes") linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) require.NoError(t, err, "Error deploying LINK token") - registry, registrar := actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( t, chainClient, rv, @@ -287,8 +286,8 @@ func TestAutomationChaos(t *testing.T) { } require.NoError(t, err, "Error setting OCR config") - consumersConditional, upkeepidsConditional := actions_seth.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false) - consumersLogtrigger, upkeepidsLogtrigger := actions_seth.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false) + consumersConditional, upkeepidsConditional := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false) + consumersLogtrigger, upkeepidsLogtrigger := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false) consumers := append(consumersConditional, consumersLogtrigger...) upkeepIDs := append(upkeepidsConditional, upkeepidsLogtrigger...) diff --git a/integration-tests/chaos/ocr2vrf_chaos_test.go b/integration-tests/chaos/ocr2vrf_chaos_test.go index dfd1efaefe..2800e763f1 100644 --- a/integration-tests/chaos/ocr2vrf_chaos_test.go +++ b/integration-tests/chaos/ocr2vrf_chaos_test.go @@ -20,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -157,7 +156,7 @@ func TestOCR2VRFChaos(t *testing.T) { require.NoError(t, err) testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(testconfig, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(testconfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -166,7 +165,7 @@ func TestOCR2VRFChaos(t *testing.T) { require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &testconfig) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &testconfig) require.NoError(t, err, "Error tearing down environment") }) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 9f7dea3c25..99cc986984 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -24,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -168,14 +167,14 @@ func TestOCRChaos(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(cfg.GetNetworkConfig())[0] network = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, network, *testEnvironment) - seth, err := actions_seth.GetChainClient(&cfg, network) + seth, err := seth_utils.GetChainClient(&cfg, network) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) require.NoError(t, err, "Connecting to chainlink nodes shouldn't fail") bootstrapNode, workerNodes := chainlinkNodes[0], chainlinkNodes[1:] t.Cleanup(func() { - err := actions_seth.TeardownRemoteSuite(t, seth, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &cfg) + err := actions.TeardownRemoteSuite(t, seth, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &cfg) require.NoError(t, err, "Error tearing down environment") }) @@ -185,10 +184,10 @@ func TestOCRChaos(t *testing.T) { linkContract, err := contracts.DeployLinkTokenContract(l, seth) require.NoError(t, err, "Error deploying link token contract") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), big.NewFloat(10)) + err = actions.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), big.NewFloat(10)) require.NoError(t, err) - ocrInstances, err := actions_seth.DeployOCRv1Contracts(l, seth, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(l, seth, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) require.NoError(t, err) err = actions.CreateOCRJobs(ocrInstances, bootstrapNode, workerNodes, 5, ms, fmt.Sprint(seth.ChainID)) require.NoError(t, err) diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go deleted file mode 100644 index 99198aa635..0000000000 --- a/integration-tests/contracts/contract_deployer.go +++ /dev/null @@ -1,1898 +0,0 @@ -package contracts - -import ( - "context" - "errors" - "fmt" - "math/big" - "strings" - "time" - - "github.com/smartcontractkit/chainlink-testing-framework/networks" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/arbitrum_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" - automationForwarderLogic "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_forwarder_logic" - registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" - registrylogica22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_2" - registrylogicb22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_2" - registry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_wrapper_2_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_module_base" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_billing_registry_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_oracle_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper_mock" - iregistry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" - ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_chain_module" - iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_performance_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic1_3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic2_0" - registrylogica21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic_a_wrapper_2_1" - registrylogicb21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_logic_b_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" - registry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_aggregator_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/optimism_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/perform_data_checker_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/scroll_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" -) - -// ContractDeployer is an interface for abstracting the contract deployment methods across network implementations -type ContractDeployer interface { - DeployAPIConsumer(linkAddr string) (APIConsumer, error) - DeployOracle(linkAddr string) (Oracle, error) - DeployFlags(rac string) (Flags, error) - DeployFluxAggregatorContract(linkAddr string, fluxOptions FluxAggregatorOptions) (FluxAggregator, error) - DeployLinkTokenContract() (LinkToken, error) - DeployWERC20Mock() (WERC20Mock, error) - LoadLinkToken(address common.Address) (LinkToken, error) - DeployOffChainAggregator(linkAddr string, offchainOptions OffchainOptions) (OffchainAggregator, error) - LoadOffChainAggregator(address *common.Address) (OffchainAggregator, error) - DeployMockETHLINKFeed(answer *big.Int) (MockETHLINKFeed, error) - LoadETHLINKFeed(address common.Address) (MockETHLINKFeed, error) - DeployMockGasFeed(answer *big.Int) (MockGasFeed, error) - LoadGasFeed(address common.Address) (MockGasFeed, error) - DeployKeeperRegistrar(registryVersion eth_contracts.KeeperRegistryVersion, linkAddr string, registrarSettings KeeperRegistrarSettings) (KeeperRegistrar, error) - LoadKeeperRegistrar(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistrar, error) - DeployUpkeepTranscoder() (UpkeepTranscoder, error) - LoadUpkeepTranscoder(address common.Address) (UpkeepTranscoder, error) - DeployKeeperRegistry(opts *KeeperRegistryOpts) (KeeperRegistry, error) - LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) - DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error) - DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error) - DeployAutomationSimpleLogTriggerConsumer(isStreamsLookup bool) (KeeperConsumer, error) - DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) - DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() (KeeperConsumer, error) - DeployKeeperConsumerPerformance( - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn *big.Int, - ) (KeeperConsumerPerformance, error) - DeployKeeperConsumerBenchmark() (AutomationConsumerBenchmark, error) - LoadKeeperConsumerBenchmark(address common.Address) (AutomationConsumerBenchmark, error) - DeployKeeperPerformDataChecker(expectedData []byte) (KeeperPerformDataChecker, error) - DeployUpkeepCounter(testRange *big.Int, interval *big.Int) (UpkeepCounter, error) - DeployUpkeepPerformCounterRestrictive(testRange *big.Int, averageEligibilityCadence *big.Int) (UpkeepPerformCounterRestrictive, error) - DeployOperatorFactory(linkAddr string) (OperatorFactory, error) - DeployStaking(params eth_contracts.StakingPoolConstructorParams) (Staking, error) - DeployFunctionsLoadTestClient(router string) (FunctionsLoadTestClient, error) - DeployFunctionsOracleEventsMock() (FunctionsOracleEventsMock, error) - DeployFunctionsBillingRegistryEventsMock() (FunctionsBillingRegistryEventsMock, error) - DeployStakingEventsMock() (StakingEventsMock, error) - DeployFunctionsV1EventsMock() (FunctionsV1EventsMock, error) - DeployOffchainAggregatorEventsMock() (OffchainAggregatorEventsMock, error) - DeployMockAggregatorProxy(aggregatorAddr string) (MockAggregatorProxy, error) - DeployOffchainAggregatorV2(linkAddr string, offchainOptions OffchainOptions) (OffchainAggregatorV2, error) - LoadOffChainAggregatorV2(address *common.Address) (OffchainAggregatorV2, error) - DeployKeeperRegistryCheckUpkeepGasUsageWrapper(keeperRegistryAddr string) (KeeperRegistryCheckUpkeepGasUsageWrapper, error) - DeployKeeperRegistry11Mock() (KeeperRegistry11Mock, error) - DeployKeeperRegistrar12Mock() (KeeperRegistrar12Mock, error) - DeployKeeperGasWrapperMock() (KeeperGasWrapperMock, error) - DeployMercuryVerifierContract(verifierProxyAddr common.Address) (MercuryVerifier, error) - DeployMercuryVerifierProxyContract(accessControllerAddr common.Address) (MercuryVerifierProxy, error) - DeployMercuryFeeManager(linkAddress common.Address, nativeAddress common.Address, proxyAddress common.Address, rewardManagerAddress common.Address) (MercuryFeeManager, error) - DeployMercuryRewardManager(linkAddress common.Address) (MercuryRewardManager, error) - DeployLogEmitterContract() (LogEmitter, error) - DeployMultiCallContract() (common.Address, error) -} - -// NewContractDeployer returns an instance of a contract deployer based on the client type -func NewContractDeployer(bcClient blockchain.EVMClient, logger zerolog.Logger) (ContractDeployer, error) { - switch clientImpl := bcClient.Get().(type) { - case *blockchain.EthereumClient: - return NewEthereumContractDeployer(clientImpl, logger), nil - case *blockchain.KlaytnClient: - return &KlaytnContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.MetisClient: - return &MetisContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.ArbitrumClient: - return &MetisContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.OptimismClient: - return &OptimismContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.RSKClient: - return &RSKContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.PolygonClient: - return &PolygonContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.CeloClient: - return &CeloContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.QuorumClient: - return &QuorumContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.BSCClient: - return &BSCContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.ScrollClient: - return &ScrollContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.PolygonZkEvmClient: - return &PolygonZkEvmContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.LineaClient: - return &LineaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.FantomClient: - return &FantomContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.KromaClient: - return &KromaContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.WeMixClient: - return &WeMixContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - case *blockchain.GnosisClient: - return &GnosisContractDeployer{NewEthereumContractDeployer(clientImpl, logger)}, nil - } - return nil, errors.New("unknown blockchain client implementation for contract deployer, register blockchain client in NewContractDeployer") -} - -// EthereumContractDeployer provides the implementations for deploying ETH (EVM) based contracts -type EthereumContractDeployer struct { - client blockchain.EVMClient - l zerolog.Logger -} - -// KlaytnContractDeployer wraps ethereum contract deployments for Klaytn -type KlaytnContractDeployer struct { - *EthereumContractDeployer -} - -// MetisContractDeployer wraps ethereum contract deployments for Metis -type MetisContractDeployer struct { - *EthereumContractDeployer -} - -// ArbitrumContractDeployer wraps for Arbitrum -type ArbitrumContractDeployer struct { - *EthereumContractDeployer -} - -// OptimismContractDeployer wraps for Optimism -type OptimismContractDeployer struct { - *EthereumContractDeployer -} - -// RSKContractDeployer wraps for RSK -type RSKContractDeployer struct { - *EthereumContractDeployer -} - -type PolygonContractDeployer struct { - *EthereumContractDeployer -} - -type CeloContractDeployer struct { - *EthereumContractDeployer -} - -type QuorumContractDeployer struct { - *EthereumContractDeployer -} - -type BSCContractDeployer struct { - *EthereumContractDeployer -} - -type ScrollContractDeployer struct { - *EthereumContractDeployer -} - -type PolygonZkEvmContractDeployer struct { - *EthereumContractDeployer -} - -type LineaContractDeployer struct { - *EthereumContractDeployer -} - -type FantomContractDeployer struct { - *EthereumContractDeployer -} - -type KromaContractDeployer struct { - *EthereumContractDeployer -} - -type WeMixContractDeployer struct { - *EthereumContractDeployer -} - -type GnosisContractDeployer struct { - *EthereumContractDeployer -} - -// NewEthereumContractDeployer returns an instantiated instance of the ETH contract deployer -func NewEthereumContractDeployer(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractDeployer { - return &EthereumContractDeployer{ - client: ethClient, - l: logger, - } -} - -// DefaultFluxAggregatorOptions produces some basic defaults for a flux aggregator contract -func DefaultFluxAggregatorOptions() FluxAggregatorOptions { - return FluxAggregatorOptions{ - PaymentAmount: big.NewInt(1), - Timeout: uint32(30), - MinSubValue: big.NewInt(0), - MaxSubValue: big.NewInt(1000000000000), - Decimals: uint8(0), - Description: "Test Flux Aggregator", - } -} - -// DeployFlags deploys flags contract -func (e *EthereumContractDeployer) DeployFlags( - rac string, -) (Flags, error) { - address, _, instance, err := e.client.DeployContract("Flags", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - racAddr := common.HexToAddress(rac) - return flags_wrapper.DeployFlags(auth, backend, racAddr) - }) - if err != nil { - return nil, err - } - return &EthereumFlags{ - client: e.client, - flags: instance.(*flags_wrapper.Flags), - address: address, - }, nil -} - -// DeployFluxAggregatorContract deploys the Flux Aggregator Contract on an EVM chain -func (e *EthereumContractDeployer) DeployFluxAggregatorContract( - linkAddr string, - fluxOptions FluxAggregatorOptions, -) (FluxAggregator, error) { - address, _, instance, err := e.client.DeployContract("Flux Aggregator", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - la := common.HexToAddress(linkAddr) - return flux_aggregator_wrapper.DeployFluxAggregator(auth, - backend, - la, - fluxOptions.PaymentAmount, - fluxOptions.Timeout, - fluxOptions.Validator, - fluxOptions.MinSubValue, - fluxOptions.MaxSubValue, - fluxOptions.Decimals, - fluxOptions.Description) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFluxAggregator{ - client: e.client, - fluxAggregator: instance.(*flux_aggregator_wrapper.FluxAggregator), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployStaking(params eth_contracts.StakingPoolConstructorParams) (Staking, error) { - stakingAddress, _, instance, err := e.client.DeployContract("Staking", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return eth_contracts.DeployStaking(auth, backend, params) - }) - if err != nil { - return nil, err - } - return &EthereumStaking{ - client: e.client, - staking: instance.(*eth_contracts.Staking), - address: stakingAddress, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsLoadTestClient(router string) (FunctionsLoadTestClient, error) { - address, _, instance, err := e.client.DeployContract("FunctionsLoadTestClient", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_load_test_client.DeployFunctionsLoadTestClient(auth, backend, common.HexToAddress(router)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsLoadTestClient{ - client: e.client, - instance: instance.(*functions_load_test_client.FunctionsLoadTestClient), - address: *address, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsOracleEventsMock() (FunctionsOracleEventsMock, error) { - address, _, instance, err := e.client.DeployContract("FunctionsOracleEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_oracle_events_mock.DeployFunctionsOracleEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumFunctionsOracleEventsMock{ - client: e.client, - eventsMock: instance.(*functions_oracle_events_mock.FunctionsOracleEventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsBillingRegistryEventsMock() (FunctionsBillingRegistryEventsMock, error) { - address, _, instance, err := e.client.DeployContract("FunctionsBillingRegistryEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_billing_registry_events_mock.DeployFunctionsBillingRegistryEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumFunctionsBillingRegistryEventsMock{ - client: e.client, - eventsMock: instance.(*functions_billing_registry_events_mock.FunctionsBillingRegistryEventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployStakingEventsMock() (StakingEventsMock, error) { - address, _, instance, err := e.client.DeployContract("StakingEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return eth_contracts.DeployStakingEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumStakingEventsMock{ - client: e.client, - eventsMock: instance.(*eth_contracts.StakingEventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployFunctionsV1EventsMock() (FunctionsV1EventsMock, error) { - address, _, instance, err := e.client.DeployContract("FunctionsV1EventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return functions_v1_events_mock.DeployFunctionsV1EventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsV1EventsMock{ - client: e.client, - eventsMock: instance.(*functions_v1_events_mock.FunctionsV1EventsMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployKeeperRegistry11Mock() (KeeperRegistry11Mock, error) { - address, _, instance, err := e.client.DeployContract("KeeperRegistry11Mock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_1_mock.DeployKeeperRegistryMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry11Mock{ - client: e.client, - registryMock: instance.(*keeper_registry_wrapper1_1_mock.KeeperRegistryMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployKeeperRegistrar12Mock() (KeeperRegistrar12Mock, error) { - address, _, instance, err := e.client.DeployContract("KeeperRegistrar12Mock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registrar_wrapper1_2_mock.DeployKeeperRegistrarMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar12Mock{ - client: e.client, - registrarMock: instance.(*keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployKeeperGasWrapperMock() (KeeperGasWrapperMock, error) { - address, _, instance, err := e.client.DeployContract("KeeperGasWrapperMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return gas_wrapper_mock.DeployKeeperRegistryCheckUpkeepGasUsageWrapperMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperGasWrapperMock{ - client: e.client, - gasWrapperMock: instance.(*gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock), - address: address, - }, nil -} - -func (e *EthereumContractDeployer) DeployOffchainAggregatorEventsMock() (OffchainAggregatorEventsMock, error) { - address, _, instance, err := e.client.DeployContract("OffchainAggregatorEventsMock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return eth_contracts.DeployOffchainAggregatorEventsMock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumOffchainAggregatorEventsMock{ - client: e.client, - eventsMock: instance.(*eth_contracts.OffchainAggregatorEventsMock), - address: address, - }, nil -} - -// DeployLinkTokenContract deploys a Link Token contract to an EVM chain -func (e *EthereumContractDeployer) DeployLinkTokenContract() (LinkToken, error) { - linkTokenAddress, _, instance, err := e.client.DeployContract("LINK Token", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return link_token_interface.DeployLinkToken(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - if err != nil { - return nil, err - } - - return &LegacyEthereumLinkToken{ - client: e.client, - instance: instance.(*link_token_interface.LinkToken), - address: *linkTokenAddress, - l: e.l, - }, err -} - -// LoadLinkToken returns deployed on given address EthereumLinkToken -func (e *EthereumContractDeployer) LoadLinkToken(address common.Address) (LinkToken, error) { - instance, err := e.client.LoadContract("LinkToken", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return link_token_interface.NewLinkToken(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumLinkToken{ - address: address, - client: e.client, - instance: instance.(*link_token_interface.LinkToken), - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) NewLinkTokenContract(address common.Address) (LinkToken, error) { - return e.LoadLinkToken(address) -} - -// DefaultOffChainAggregatorOptions returns some base defaults for deploying an OCR contract -func DefaultOffChainAggregatorOptions() OffchainOptions { - return OffchainOptions{ - MaximumGasPrice: uint32(3000), - ReasonableGasPrice: uint32(10), - MicroLinkPerEth: uint32(500), - LinkGweiPerObservation: uint32(500), - LinkGweiPerTransmission: uint32(500), - MinimumAnswer: big.NewInt(1), - MaximumAnswer: big.NewInt(50000000000000000), - Decimals: 8, - Description: "Test OCR", - } -} - -// DefaultOffChainAggregatorConfig returns some base defaults for configuring an OCR contract -func DefaultOffChainAggregatorConfig(numberNodes int) OffChainAggregatorConfig { - if numberNodes <= 4 { - log.Err(fmt.Errorf("insufficient number of nodes (%d) supplied for OCR, need at least 5", numberNodes)). - Int("Number Chainlink Nodes", numberNodes). - Msg("You likely need more chainlink nodes to properly configure OCR, try 5 or more.") - } - s := []int{1} - // First node's stage already inputted as a 1 in line above, so numberNodes-1. - for i := 0; i < numberNodes-1; i++ { - s = append(s, 2) - } - return OffChainAggregatorConfig{ - AlphaPPB: 1, - DeltaC: time.Minute * 60, - DeltaGrace: time.Second * 12, - DeltaProgress: time.Second * 35, - DeltaStage: time.Second * 60, - DeltaResend: time.Second * 17, - DeltaRound: time.Second * 30, - RMax: 6, - S: s, - N: numberNodes, - F: 1, - OracleIdentities: []ocrConfigHelper.OracleIdentityExtra{}, - } -} - -// DeployOffChainAggregator deploys the offchain aggregation contract to the EVM chain -func (e *EthereumContractDeployer) DeployOffChainAggregator( - linkAddr string, - offchainOptions OffchainOptions, -) (OffchainAggregator, error) { - address, _, instance, err := e.client.DeployContract("OffChain Aggregator", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - la := common.HexToAddress(linkAddr) - return offchainaggregator.DeployOffchainAggregator(auth, - backend, - offchainOptions.MaximumGasPrice, - offchainOptions.ReasonableGasPrice, - offchainOptions.MicroLinkPerEth, - offchainOptions.LinkGweiPerObservation, - offchainOptions.LinkGweiPerTransmission, - la, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregator{ - client: e.client, - ocr: instance.(*offchainaggregator.OffchainAggregator), - address: address, - l: e.l, - }, err -} - -// LoadOffChainAggregator loads an already deployed offchain aggregator contract -func (e *EthereumContractDeployer) LoadOffChainAggregator(address *common.Address) (OffchainAggregator, error) { - instance, err := e.client.LoadContract("OffChainAggregator", *address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return offchainaggregator.NewOffchainAggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregator{ - address: address, - client: e.client, - ocr: instance.(*offchainaggregator.OffchainAggregator), - l: e.l, - }, err -} - -// DeployAPIConsumer deploys api consumer for oracle -func (e *EthereumContractDeployer) DeployAPIConsumer(linkAddr string) (APIConsumer, error) { - addr, _, instance, err := e.client.DeployContract("TestAPIConsumer", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return test_api_consumer_wrapper.DeployTestAPIConsumer(auth, backend, common.HexToAddress(linkAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAPIConsumer{ - address: addr, - client: e.client, - consumer: instance.(*test_api_consumer_wrapper.TestAPIConsumer), - }, err -} - -// DeployOracle deploys oracle for consumer test -func (e *EthereumContractDeployer) DeployOracle(linkAddr string) (Oracle, error) { - addr, _, instance, err := e.client.DeployContract("Oracle", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return oracle_wrapper.DeployOracle(auth, backend, common.HexToAddress(linkAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOracle{ - address: addr, - client: e.client, - oracle: instance.(*oracle_wrapper.Oracle), - }, err -} - -func (e *EthereumContractDeployer) DeployMockETHLINKFeed(answer *big.Int) (MockETHLINKFeed, error) { - address, _, instance, err := e.client.DeployContract("MockETHLINKAggregator", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return mock_ethlink_aggregator_wrapper.DeployMockETHLINKAggregator(auth, wrappers.MustNewWrappedContractBackend(e.client, nil), answer) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockETHLINKFeed{ - client: e.client, - feed: instance.(*mock_ethlink_aggregator_wrapper.MockETHLINKAggregator), - address: address, - }, err -} - -// LoadETHLINKFeed returns deployed on given address EthereumMockETHLINKFeed -func (e *EthereumContractDeployer) LoadETHLINKFeed(address common.Address) (MockETHLINKFeed, error) { - instance, err := e.client.LoadContract("MockETHLINKFeed", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockETHLINKFeed{ - address: &address, - client: e.client, - feed: instance.(*mock_ethlink_aggregator_wrapper.MockETHLINKAggregator), - }, err -} - -func (e *EthereumContractDeployer) DeployMockGasFeed(answer *big.Int) (MockGasFeed, error) { - address, _, instance, err := e.client.DeployContract("MockGasFeed", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return mock_gas_aggregator_wrapper.DeployMockGASAggregator(auth, wrappers.MustNewWrappedContractBackend(e.client, nil), answer) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockGASFeed{ - client: e.client, - feed: instance.(*mock_gas_aggregator_wrapper.MockGASAggregator), - address: address, - }, err -} - -// LoadGasFeed returns deployed on given address EthereumMockGASFeed -func (e *EthereumContractDeployer) LoadGasFeed(address common.Address) (MockGasFeed, error) { - instance, err := e.client.LoadContract("MockETHLINKFeed", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return mock_gas_aggregator_wrapper.NewMockGASAggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumMockGASFeed{ - address: &address, - client: e.client, - feed: instance.(*mock_gas_aggregator_wrapper.MockGASAggregator), - }, err -} - -func (e *EthereumContractDeployer) DeployUpkeepTranscoder() (UpkeepTranscoder, error) { - address, _, instance, err := e.client.DeployContract("UpkeepTranscoder", func( - opts *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return upkeep_transcoder.DeployUpkeepTranscoder(opts, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumUpkeepTranscoder{ - client: e.client, - transcoder: instance.(*upkeep_transcoder.UpkeepTranscoder), - address: address, - }, err -} - -func (e *EthereumContractDeployer) LoadUpkeepTranscoder(address common.Address) (UpkeepTranscoder, error) { - instance, err := e.client.LoadContract("UpkeepTranscoder", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return upkeep_transcoder.NewUpkeepTranscoder(address, backend) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumUpkeepTranscoder{ - client: e.client, - transcoder: instance.(*upkeep_transcoder.UpkeepTranscoder), - address: &address, - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperRegistrar(registryVersion eth_contracts.KeeperRegistryVersion, linkAddr string, - registrarSettings KeeperRegistrarSettings) (KeeperRegistrar, error) { - - if registryVersion == eth_contracts.RegistryVersion_2_0 { - // deploy registrar 2.0 - address, _, instance, err := e.client.DeployContract("KeeperRegistrar", func( - opts *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registrar_wrapper2_0.DeployKeeperRegistrar(opts, wrappers.MustNewWrappedContractBackend(e.client, nil), common.HexToAddress(linkAddr), registrarSettings.AutoApproveConfigType, - registrarSettings.AutoApproveMaxAllowed, common.HexToAddress(registrarSettings.RegistryAddr), registrarSettings.MinLinkJuels) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistrar{ - client: e.client, - registrar20: instance.(*keeper_registrar_wrapper2_0.KeeperRegistrar), - address: address, - }, err - } else if registryVersion == eth_contracts.RegistryVersion_2_1 || registryVersion == eth_contracts.RegistryVersion_2_2 { // both 2.1 and 2.2 registry use registrar 2.1 - // deploy registrar 2.1 - address, _, instance, err := e.client.DeployContract("AutomationRegistrar", func( - opts *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - // set default TriggerType to 0(conditional), AutoApproveConfigType to 2(auto approve enabled), AutoApproveMaxAllowed to 1000 - triggerConfigs := []registrar21.AutomationRegistrar21InitialTriggerConfig{ - {TriggerType: 0, AutoApproveType: registrarSettings.AutoApproveConfigType, - AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, - {TriggerType: 1, AutoApproveType: registrarSettings.AutoApproveConfigType, - AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, - } - - return registrar21.DeployAutomationRegistrar( - opts, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(linkAddr), - common.HexToAddress(registrarSettings.RegistryAddr), - registrarSettings.MinLinkJuels, - triggerConfigs) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistrar{ - client: e.client, - registrar21: instance.(*registrar21.AutomationRegistrar), - address: address, - }, err - } - // non OCR registrar - address, _, instance, err := e.client.DeployContract("KeeperRegistrar", func( - opts *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registrar_wrapper1_2.DeployKeeperRegistrar(opts, backend, common.HexToAddress(linkAddr), registrarSettings.AutoApproveConfigType, - registrarSettings.AutoApproveMaxAllowed, common.HexToAddress(registrarSettings.RegistryAddr), registrarSettings.MinLinkJuels) - }) - - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistrar{ - client: e.client, - registrar: instance.(*keeper_registrar_wrapper1_2.KeeperRegistrar), - address: address, - }, err -} - -// LoadKeeperRegistrar returns deployed on given address EthereumKeeperRegistrar -func (e *EthereumContractDeployer) LoadKeeperRegistrar(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistrar, error) { - if registryVersion == eth_contracts.RegistryVersion_1_1 || registryVersion == eth_contracts.RegistryVersion_1_2 || - registryVersion == eth_contracts.RegistryVersion_1_3 { - instance, err := e.client.LoadContract("KeeperRegistrar", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registrar_wrapper1_2.NewKeeperRegistrar(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar{ - address: &address, - client: e.client, - registrar: instance.(*keeper_registrar_wrapper1_2.KeeperRegistrar), - }, err - } else if registryVersion == eth_contracts.RegistryVersion_2_0 { - instance, err := e.client.LoadContract("KeeperRegistrar", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registrar_wrapper2_0.NewKeeperRegistrar(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar{ - address: &address, - client: e.client, - registrar20: instance.(*keeper_registrar_wrapper2_0.KeeperRegistrar), - }, err - } - instance, err := e.client.LoadContract("AutomationRegistrar", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return registrar21.NewAutomationRegistrar(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistrar{ - address: &address, - client: e.client, - registrar21: instance.(*registrar21.AutomationRegistrar), - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperRegistry( - opts *KeeperRegistryOpts, -) (KeeperRegistry, error) { - var mode uint8 - switch e.client.GetChainID().Int64() { - //Arbitrum payment model - case networks.ArbitrumMainnet.ChainID, networks.ArbitrumSepolia.ChainID: - mode = uint8(1) - //Optimism payment model - case networks.OptimismMainnet.ChainID, networks.OptimismSepolia.ChainID: - mode = uint8(2) - //Base - case networks.BaseMainnet.ChainID, networks.BaseSepolia.ChainID: - mode = uint8(2) - default: - mode = uint8(0) - } - registryGasOverhead := big.NewInt(80000) - switch opts.RegistryVersion { - case eth_contracts.RegistryVersion_1_0, eth_contracts.RegistryVersion_1_1: - address, _, instance, err := e.client.DeployContract("KeeperRegistry1_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_1.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - opts.Settings.PaymentPremiumPPB, - opts.Settings.FlatFeeMicroLINK, - opts.Settings.BlockCountPerTurn, - opts.Settings.CheckGasLimit, - opts.Settings.StalenessSeconds, - opts.Settings.GasCeilingMultiplier, - opts.Settings.FallbackGasPrice, - opts.Settings.FallbackLinkPrice, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_1_1, - registry1_1: instance.(*keeper_registry_wrapper1_1.KeeperRegistry), - registry1_2: nil, - registry1_3: nil, - address: address, - }, err - case eth_contracts.RegistryVersion_1_2: - address, _, instance, err := e.client.DeployContract("KeeperRegistry1_2", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_2.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: opts.Settings.PaymentPremiumPPB, - FlatFeeMicroLink: opts.Settings.FlatFeeMicroLINK, - BlockCountPerTurn: opts.Settings.BlockCountPerTurn, - CheckGasLimit: opts.Settings.CheckGasLimit, - StalenessSeconds: opts.Settings.StalenessSeconds, - GasCeilingMultiplier: opts.Settings.GasCeilingMultiplier, - MinUpkeepSpend: opts.Settings.MinUpkeepSpend, - MaxPerformGas: opts.Settings.MaxPerformGas, - FallbackGasPrice: opts.Settings.FallbackGasPrice, - FallbackLinkPrice: opts.Settings.FallbackLinkPrice, - Transcoder: common.HexToAddress(opts.TranscoderAddr), - Registrar: common.HexToAddress(opts.RegistrarAddr), - }, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_1_2, - registry1_1: nil, - registry1_2: instance.(*keeper_registry_wrapper1_2.KeeperRegistry), - registry1_3: nil, - address: address, - }, err - case eth_contracts.RegistryVersion_1_3: - logicAddress, _, _, err := e.client.DeployContract("KeeperRegistryLogic1_3", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_logic1_3.DeployKeeperRegistryLogic( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - mode, // Default payment model - registryGasOverhead, // Registry gas overhead - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - ) - }) - if err != nil { - return nil, err - } - err = e.client.WaitForEvents() - if err != nil { - return nil, err - } - - address, _, instance, err := e.client.DeployContract("KeeperRegistry1_3", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_wrapper1_3.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *logicAddress, - keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: opts.Settings.PaymentPremiumPPB, - FlatFeeMicroLink: opts.Settings.FlatFeeMicroLINK, - BlockCountPerTurn: opts.Settings.BlockCountPerTurn, - CheckGasLimit: opts.Settings.CheckGasLimit, - StalenessSeconds: opts.Settings.StalenessSeconds, - GasCeilingMultiplier: opts.Settings.GasCeilingMultiplier, - MinUpkeepSpend: opts.Settings.MinUpkeepSpend, - MaxPerformGas: opts.Settings.MaxPerformGas, - FallbackGasPrice: opts.Settings.FallbackGasPrice, - FallbackLinkPrice: opts.Settings.FallbackLinkPrice, - Transcoder: common.HexToAddress(opts.TranscoderAddr), - Registrar: common.HexToAddress(opts.RegistrarAddr), - }, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_1_3, - registry1_1: nil, - registry1_2: nil, - registry1_3: instance.(*keeper_registry_wrapper1_3.KeeperRegistry), - address: address, - }, err - case eth_contracts.RegistryVersion_2_0: - logicAddress, _, _, err := e.client.DeployContract("KeeperRegistryLogic2_0", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_registry_logic2_0.DeployKeeperRegistryLogic( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - mode, // Default payment model - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - ) - }) - if err != nil { - return nil, err - } - err = e.client.WaitForEvents() - if err != nil { - return nil, err - } - - address, _, instance, err := e.client.DeployContract("KeeperRegistry2_0", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return keeper_registry_wrapper2_0.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *logicAddress, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_2_0, - registry2_0: instance.(*keeper_registry_wrapper2_0.KeeperRegistry), - address: address, - }, err - - case eth_contracts.RegistryVersion_2_1: - automationForwarderLogicAddr, err := deployAutomationForwarderLogic(e.client) - if err != nil { - return nil, err - } - - registryLogicBAddr, _, _, err := e.client.DeployContract("KeeperRegistryLogicB2_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogicb21.DeployKeeperRegistryLogicB( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - mode, - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - *automationForwarderLogicAddr, - ) - }) - if err != nil { - return nil, err - } - - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryLogicAAddr, _, _, err := e.client.DeployContract("KeeperRegistryLogicA2_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogica21.DeployKeeperRegistryLogicA( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicBAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - address, _, _, err := e.client.DeployContract("KeeperRegistry2_1", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return registry21.DeployKeeperRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicAAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryMaster, err := iregistry21.NewIKeeperRegistryMaster( - *address, - wrappers.MustNewWrappedContractBackend(e.client, nil), - ) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_2_1, - registry2_1: registryMaster, - address: address, - }, err - case eth_contracts.RegistryVersion_2_2: - var chainModuleAddr *common.Address - var err error - chainId := e.client.GetChainID().Int64() - - if chainId == networks.ScrollMainnet.ChainID || chainId == networks.ScrollSepolia.ChainID { - chainModuleAddr, _, _, err = e.client.DeployContract("ScrollModule", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return scroll_module.DeployScrollModule(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } else if chainId == networks.ArbitrumMainnet.ChainID || chainId == networks.ArbitrumSepolia.ChainID { - chainModuleAddr, _, _, err = e.client.DeployContract("ArbitrumModule", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return arbitrum_module.DeployArbitrumModule(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } else if chainId == networks.OptimismMainnet.ChainID || chainId == networks.OptimismSepolia.ChainID { - chainModuleAddr, _, _, err = e.client.DeployContract("OptimismModule", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return optimism_module.DeployOptimismModule(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } else { - chainModuleAddr, _, _, err = e.client.DeployContract("ChainModuleBase", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return chain_module_base.DeployChainModuleBase(auth, wrappers.MustNewWrappedContractBackend(e.client, nil)) - }) - } - if err != nil { - return nil, err - } - if err = e.client.WaitForEvents(); err != nil { - return nil, err - } - - automationForwarderLogicAddr, err := deployAutomationForwarderLogic(e.client) - if err != nil { - return nil, err - } - - var allowedReadOnlyAddress common.Address - if chainId == networks.PolygonZkEvmMainnet.ChainID || chainId == networks.PolygonZkEvmCardona.ChainID { - allowedReadOnlyAddress = common.HexToAddress("0x1111111111111111111111111111111111111111") - } else { - allowedReadOnlyAddress = common.HexToAddress("0x0000000000000000000000000000000000000000") - } - registryLogicBAddr, _, _, err := e.client.DeployContract("AutomationRegistryLogicB2_2", func( - auth *bind.TransactOpts, - _ bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogicb22.DeployAutomationRegistryLogicB( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - common.HexToAddress(opts.LinkAddr), - common.HexToAddress(opts.ETHFeedAddr), - common.HexToAddress(opts.GasFeedAddr), - *automationForwarderLogicAddr, - allowedReadOnlyAddress, - ) - }) - if err != nil { - return nil, err - } - - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryLogicAAddr, _, _, err := e.client.DeployContract("AutomationRegistryLogicA2_2", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - - return registrylogica22.DeployAutomationRegistryLogicA( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicBAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - address, _, _, err := e.client.DeployContract("AutomationRegistry2_2", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return registry22.DeployAutomationRegistry( - auth, - wrappers.MustNewWrappedContractBackend(e.client, nil), - *registryLogicAAddr, - ) - }) - if err != nil { - return nil, err - } - if err := e.client.WaitForEvents(); err != nil { - return nil, err - } - - registryMaster, err := iregistry22.NewIAutomationRegistryMaster( - *address, - wrappers.MustNewWrappedContractBackend(e.client, nil), - ) - if err != nil { - return nil, err - } - - chainModule, err := i_chain_module.NewIChainModule( - *chainModuleAddr, - wrappers.MustNewWrappedContractBackend(e.client, nil), - ) - if err != nil { - return nil, err - } - - return &LegacyEthereumKeeperRegistry{ - client: e.client, - version: eth_contracts.RegistryVersion_2_2, - registry2_2: registryMaster, - chainModule: chainModule, - address: address, - }, err - default: - return nil, fmt.Errorf("keeper registry version %d is not supported", opts.RegistryVersion) - } -} - -func deployAutomationForwarderLogic(client blockchain.EVMClient) (*common.Address, error) { - automationForwarderLogicAddr, _, _, err := client.DeployContract("automationForwarderLogic", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return automationForwarderLogic.DeployAutomationForwarderLogic(auth, backend) - }) - - if err != nil { - return nil, err - } - - if err := client.WaitForEvents(); err != nil { - return nil, err - } - return automationForwarderLogicAddr, nil -} - -// LoadKeeperRegistry returns deployed on given address EthereumKeeperRegistry -func (e *EthereumContractDeployer) LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) { - switch registryVersion { - case eth_contracts.RegistryVersion_1_1: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper1_1.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry1_1: instance.(*keeper_registry_wrapper1_1.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_1_2: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper1_2.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry1_2: instance.(*keeper_registry_wrapper1_2.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_1_3: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper1_3.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry1_3: instance.(*keeper_registry_wrapper1_3.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_2_0: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return keeper_registry_wrapper2_0.NewKeeperRegistry(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry2_0: instance.(*keeper_registry_wrapper2_0.KeeperRegistry), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_2_1: - instance, err := e.client.LoadContract("KeeperRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return ac.NewIAutomationV21PlusCommon(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry2_1: instance.(*iregistry21.IKeeperRegistryMaster), - version: registryVersion, - }, err - case eth_contracts.RegistryVersion_2_2: // why the contract name is not the same as the actual contract name? - instance, err := e.client.LoadContract("AutomationRegistry", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return iregistry22.NewIAutomationRegistryMaster(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperRegistry{ - address: &address, - client: e.client, - registry2_2: instance.(*iregistry22.IAutomationRegistryMaster), - version: registryVersion, - }, err - default: - return nil, fmt.Errorf("keeper registry version %d is not supported", registryVersion) - } -} - -func (e *EthereumContractDeployer) DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("KeeperConsumer", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_consumer_wrapper.DeployKeeperConsumer(auth, backend, updateInterval) - }) - if err != nil { - return nil, err - } - return &EthereumKeeperConsumer{ - client: e.client, - consumer: instance.(*keeper_consumer_wrapper.KeeperConsumer), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("LogUpkeepCounter", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return log_upkeep_counter_wrapper.DeployLogUpkeepCounter( - auth, wrappers.MustNewWrappedContractBackend(e.client, nil), testInterval, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationLogCounterConsumer{ - client: e.client, - consumer: instance.(*log_upkeep_counter_wrapper.LogUpkeepCounter), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationSimpleLogTriggerConsumer(isStreamsLookup bool) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("SimpleLogUpkeepCounter", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return simple_log_upkeep_counter_wrapper.DeploySimpleLogUpkeepCounter( - auth, backend, isStreamsLookup, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationSimpleLogCounterConsumer{ - client: e.client, - consumer: instance.(*simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounter), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("StreamsLookupUpkeep", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return streams_lookup_upkeep_wrapper.DeployStreamsLookupUpkeep( - auth, wrappers.MustNewWrappedContractBackend(e.client, nil), testRange, interval, useArbBlock, staging, verify, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationStreamsLookupUpkeepConsumer{ - client: e.client, - consumer: instance.(*streams_lookup_upkeep_wrapper.StreamsLookupUpkeep), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() (KeeperConsumer, error) { - address, _, instance, err := e.client.DeployContract("LogTriggeredStreamsLookupUpkeep", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return log_triggered_streams_lookup_wrapper.DeployLogTriggeredStreamsLookup( - auth, wrappers.MustNewWrappedContractBackend(e.client, nil), false, false, false, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer{ - client: e.client, - consumer: instance.(*log_triggered_streams_lookup_wrapper.LogTriggeredStreamsLookup), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployUpkeepCounter(testRange *big.Int, interval *big.Int) (UpkeepCounter, error) { - address, _, instance, err := e.client.DeployContract("UpkeepCounter", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return upkeep_counter_wrapper.DeployUpkeepCounter(auth, wrappers.MustNewWrappedContractBackend(e.client, nil), testRange, interval) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumUpkeepCounter{ - client: e.client, - consumer: instance.(*upkeep_counter_wrapper.UpkeepCounter), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployUpkeepPerformCounterRestrictive(testRange *big.Int, averageEligibilityCadence *big.Int) (UpkeepPerformCounterRestrictive, error) { - address, _, instance, err := e.client.DeployContract("UpkeepPerformCounterRestrictive", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return upkeep_perform_counter_restrictive_wrapper.DeployUpkeepPerformCounterRestrictive(auth, backend, testRange, averageEligibilityCadence) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumUpkeepPerformCounterRestrictive{ - client: e.client, - consumer: instance.(*upkeep_perform_counter_restrictive_wrapper.UpkeepPerformCounterRestrictive), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperConsumerPerformance( - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn *big.Int, -) (KeeperConsumerPerformance, error) { - address, _, instance, err := e.client.DeployContract("KeeperConsumerPerformance", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return keeper_consumer_performance_wrapper.DeployKeeperConsumerPerformance( - auth, - backend, - testBlockRange, - averageCadence, - checkGasToBurn, - performGasToBurn, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperConsumerPerformance{ - client: e.client, - consumer: instance.(*keeper_consumer_performance_wrapper.KeeperConsumerPerformance), - address: address, - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperConsumerBenchmark() (AutomationConsumerBenchmark, error) { - address, _, instance, err := e.client.DeployContract("AutomationConsumerBenchmark", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return automation_consumer_benchmark.DeployAutomationConsumerBenchmark( - auth, - backend, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationConsumerBenchmark{ - client: e.client, - consumer: instance.(*automation_consumer_benchmark.AutomationConsumerBenchmark), - address: address, - }, err -} - -// LoadKeeperConsumerBenchmark returns deployed on given address EthereumAutomationConsumerBenchmark -func (e *EthereumContractDeployer) LoadKeeperConsumerBenchmark(address common.Address) (AutomationConsumerBenchmark, error) { - instance, err := e.client.LoadContract("AutomationConsumerBenchmark", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return automation_consumer_benchmark.NewAutomationConsumerBenchmark(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAutomationConsumerBenchmark{ - address: &address, - client: e.client, - consumer: instance.(*automation_consumer_benchmark.AutomationConsumerBenchmark), - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperPerformDataChecker(expectedData []byte) (KeeperPerformDataChecker, error) { - address, _, instance, err := e.client.DeployContract("PerformDataChecker", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return perform_data_checker_wrapper.DeployPerformDataChecker( - auth, - backend, - expectedData, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumKeeperPerformDataCheckerConsumer{ - client: e.client, - performDataChecker: instance.(*perform_data_checker_wrapper.PerformDataChecker), - address: address, - }, err -} - -// DeployOperatorFactory deploys operator factory contract -func (e *EthereumContractDeployer) DeployOperatorFactory(linkAddr string) (OperatorFactory, error) { - addr, _, instance, err := e.client.DeployContract("OperatorFactory", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return operator_factory.DeployOperatorFactory(auth, backend, common.HexToAddress(linkAddr)) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOperatorFactory{ - address: addr, - client: e.client, - operatorFactory: instance.(*operator_factory.OperatorFactory), - }, err -} - -// DeployMockAggregatorProxy deploys a mock aggregator proxy contract -func (e *EthereumContractDeployer) DeployMockAggregatorProxy(aggregatorAddr string) (MockAggregatorProxy, error) { - addr, _, instance, err := e.client.DeployContract("MockAggregatorProxy", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return mock_aggregator_proxy.DeployMockAggregatorProxy(auth, backend, common.HexToAddress(aggregatorAddr)) - }) - if err != nil { - return nil, err - } - return &EthereumMockAggregatorProxy{ - address: addr, - client: e.client, - mockAggregatorProxy: instance.(*mock_aggregator_proxy.MockAggregatorProxy), - }, err -} - -func (e *EthereumContractDeployer) DeployKeeperRegistryCheckUpkeepGasUsageWrapper(keeperRegistryAddr string) (KeeperRegistryCheckUpkeepGasUsageWrapper, error) { - addr, _, instance, err := e.client.DeployContract("KeeperRegistryCheckUpkeepGasUsageWrapper", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return gas_wrapper.DeployKeeperRegistryCheckUpkeepGasUsageWrapper(auth, backend, common.HexToAddress(keeperRegistryAddr)) - }) - if err != nil { - return nil, err - } - return &EthereumKeeperRegistryCheckUpkeepGasUsageWrapper{ - address: addr, - client: e.client, - gasUsageWrapper: instance.(*gas_wrapper.KeeperRegistryCheckUpkeepGasUsageWrapper), - }, err -} - -// DeployOffChainAggregator deploys the offchain aggregation contract to the EVM chain -func (e *EthereumContractDeployer) DeployOffchainAggregatorV2( - linkAddr string, - offchainOptions OffchainOptions, -) (OffchainAggregatorV2, error) { - address, _, instance, err := e.client.DeployContract("OffChain Aggregator v2", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - la := common.HexToAddress(linkAddr) - return ocr2aggregator.DeployOCR2Aggregator( - auth, - backend, - la, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description, - ) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregatorV2{ - client: e.client, - contract: instance.(*ocr2aggregator.OCR2Aggregator), - address: address, - l: e.l, - }, err -} - -// LoadOffChainAggregatorV2 loads an already deployed offchain aggregator v2 contract -func (e *EthereumContractDeployer) LoadOffChainAggregatorV2(address *common.Address) (OffchainAggregatorV2, error) { - instance, err := e.client.LoadContract("OffChainAggregatorV2", *address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return ocr2aggregator.NewOCR2Aggregator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOffchainAggregatorV2{ - client: e.client, - contract: instance.(*ocr2aggregator.OCR2Aggregator), - address: address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryVerifierContract(verifierProxyAddr common.Address) (MercuryVerifier, error) { - address, _, instance, err := e.client.DeployContract("Mercury Verifier", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return verifier.DeployVerifier(auth, backend, verifierProxyAddr) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifier{ - client: e.client, - instance: instance.(*verifier.Verifier), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryVerifierProxyContract(accessControllerAddr common.Address) (MercuryVerifierProxy, error) { - address, _, instance, err := e.client.DeployContract("Mercury Verifier Proxy", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return verifier_proxy.DeployVerifierProxy(auth, backend, accessControllerAddr) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifierProxy{ - client: e.client, - instance: instance.(*verifier_proxy.VerifierProxy), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryFeeManager(linkAddress common.Address, nativeAddress common.Address, proxyAddress common.Address, rewardManagerAddress common.Address) (MercuryFeeManager, error) { - address, _, instance, err := e.client.DeployContract("Mercury Fee Manager", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return fee_manager.DeployFeeManager(auth, backend, linkAddress, nativeAddress, proxyAddress, rewardManagerAddress) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryFeeManager{ - client: e.client, - instance: instance.(*fee_manager.FeeManager), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMercuryRewardManager(linkAddress common.Address) (MercuryRewardManager, error) { - address, _, instance, err := e.client.DeployContract("Mercury Reward Manager", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return reward_manager.DeployRewardManager(auth, backend, linkAddress) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryRewardManager{ - client: e.client, - instance: instance.(*reward_manager.RewardManager), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployWERC20Mock() (WERC20Mock, error) { - address, _, instance, err := e.client.DeployContract("WERC20 Mock", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return werc20_mock.DeployWERC20Mock(auth, backend) - }) - if err != nil { - return nil, err - } - return &EthereumWERC20Mock{ - client: e.client, - instance: instance.(*werc20_mock.WERC20Mock), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployLogEmitterContract() (LogEmitter, error) { - address, _, instance, err := e.client.DeployContract("Log Emitter", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - return le.DeployLogEmitter(auth, backend) - }) - if err != nil { - return nil, err - } - return &LegacyLogEmitterContract{ - client: e.client, - instance: instance.(*le.LogEmitter), - address: *address, - l: e.l, - }, err -} - -func (e *EthereumContractDeployer) DeployMultiCallContract() (common.Address, error) { - multiCallABI, err := abi.JSON(strings.NewReader(MultiCallABI)) - if err != nil { - return common.Address{}, err - } - address, tx, _, err := e.client.DeployContract("MultiCall Contract", func( - auth *bind.TransactOpts, - backend bind.ContractBackend, - ) (common.Address, *types.Transaction, interface{}, error) { - address, tx, contract, err := bind.DeployContract(auth, multiCallABI, common.FromHex(MultiCallBIN), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, contract, err - }) - if err != nil { - return common.Address{}, err - } - r, err := bind.WaitMined(context.Background(), e.client.DeployBackend(), tx) - if err != nil { - return common.Address{}, err - } - if r.Status != types.ReceiptStatusSuccessful { - return common.Address{}, fmt.Errorf("deploy multicall failed") - } - return *address, nil - -} diff --git a/integration-tests/contracts/contract_loader.go b/integration-tests/contracts/contract_loader.go deleted file mode 100644 index 0cfa53b81f..0000000000 --- a/integration-tests/contracts/contract_loader.go +++ /dev/null @@ -1,428 +0,0 @@ -package contracts - -import ( - "errors" - "fmt" - - "github.com/smartcontractkit/seth" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" -) - -// ContractLoader is an interface for abstracting the contract loading methods across network implementations -type ContractLoader interface { - LoadLINKToken(address string) (LinkToken, error) - LoadOperatorContract(address common.Address) (Operator, error) - LoadAuthorizedForwarder(address common.Address) (AuthorizedForwarder, error) - - /* functions 1_0_0 */ - LoadFunctionsCoordinator(addr string) (FunctionsCoordinator, error) - LoadFunctionsRouter(addr string) (FunctionsRouter, error) - LoadFunctionsLoadTestClient(addr string) (FunctionsLoadTestClient, error) - - // Mercury - LoadMercuryVerifier(addr common.Address) (MercuryVerifier, error) - LoadMercuryVerifierProxy(addr common.Address) (MercuryVerifierProxy, error) - LoadMercuryFeeManager(addr common.Address) (MercuryFeeManager, error) - LoadMercuryRewardManager(addr common.Address) (MercuryRewardManager, error) - - LoadWERC20Mock(addr common.Address) (WERC20Mock, error) -} - -// NewContractLoader returns an instance of a contract Loader based on the client type -func NewContractLoader(bcClient blockchain.EVMClient, logger zerolog.Logger) (ContractLoader, error) { - switch clientImpl := bcClient.Get().(type) { - case *blockchain.EthereumClient: - return NewEthereumContractLoader(clientImpl, logger), nil - case *blockchain.KlaytnClient: - return &KlaytnContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.MetisClient: - return &MetisContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.ArbitrumClient: - return &ArbitrumContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.PolygonClient: - return &PolygonContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.OptimismClient: - return &OptimismContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.PolygonZkEvmClient: - return &PolygonZkEvmContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.WeMixClient: - return &WeMixContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.LineaClient: - return &LineaContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.CeloClient: - return &CeloContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.ScrollClient: - return &ScrollContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.FantomClient: - return &FantomContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.BSCClient: - return &BSCContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - case *blockchain.GnosisClient: - return &GnosisContractLoader{NewEthereumContractLoader(clientImpl, logger)}, nil - } - return nil, errors.New("unknown blockchain client implementation for contract Loader, register blockchain client in NewContractLoader") -} - -// EthereumContractLoader provides the implementations for deploying ETH (EVM) based contracts -type EthereumContractLoader struct { - client blockchain.EVMClient - l zerolog.Logger -} - -// KlaytnContractLoader wraps ethereum contract deployments for Klaytn -type KlaytnContractLoader struct { - *EthereumContractLoader -} - -// MetisContractLoader wraps ethereum contract deployments for Metis -type MetisContractLoader struct { - *EthereumContractLoader -} - -// ArbitrumContractLoader wraps for Arbitrum -type ArbitrumContractLoader struct { - *EthereumContractLoader -} - -// PolygonContractLoader wraps for Polygon -type PolygonContractLoader struct { - *EthereumContractLoader -} - -// OptimismContractLoader wraps for Optimism -type OptimismContractLoader struct { - *EthereumContractLoader -} -type PolygonZkEvmContractLoader struct { - *EthereumContractLoader -} - -// PolygonZKEVMContractLoader wraps for Polygon zkEVM -type PolygonZKEVMContractLoader struct { - *EthereumContractLoader -} - -// WeMixContractLoader wraps for WeMix -type WeMixContractLoader struct { - *EthereumContractLoader -} - -// LineaContractLoader wraps for Linea -type LineaContractLoader struct { - *EthereumContractLoader -} - -// CeloContractLoader wraps for Celo -type CeloContractLoader struct { - *EthereumContractLoader -} - -// ScrollContractLoader wraps for Scroll -type ScrollContractLoader struct { - *EthereumContractLoader -} - -// FantomContractLoader wraps for Fantom -type FantomContractLoader struct { - *EthereumContractLoader -} - -// BSCContractLoader wraps for BSC -type BSCContractLoader struct { - *EthereumContractLoader -} - -// GnosisContractLoader wraps for Gnosis -type GnosisContractLoader struct { - *EthereumContractLoader -} - -// NewEthereumContractLoader returns an instantiated instance of the ETH contract Loader -func NewEthereumContractLoader(ethClient blockchain.EVMClient, logger zerolog.Logger) *EthereumContractLoader { - return &EthereumContractLoader{ - client: ethClient, - l: logger, - } -} - -// LoadLINKToken returns deployed on given address LINK Token contract instance -func (e *EthereumContractLoader) LoadLINKToken(addr string) (LinkToken, error) { - instance, err := e.client.LoadContract("LINK Token", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return link_token_interface.NewLinkToken(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumLinkToken{ - client: e.client, - instance: instance.(*link_token_interface.LinkToken), - address: common.HexToAddress(addr), - l: e.l, - }, err -} - -// LoadFunctionsCoordinator returns deployed on given address FunctionsCoordinator contract instance -func (e *EthereumContractLoader) LoadFunctionsCoordinator(addr string) (FunctionsCoordinator, error) { - instance, err := e.client.LoadContract("Functions Coordinator", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return functions_coordinator.NewFunctionsCoordinator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsCoordinator{ - client: e.client, - instance: instance.(*functions_coordinator.FunctionsCoordinator), - address: common.HexToAddress(addr), - }, err -} - -// LoadFunctionsRouter returns deployed on given address FunctionsRouter contract instance -func (e *EthereumContractLoader) LoadFunctionsRouter(addr string) (FunctionsRouter, error) { - instance, err := e.client.LoadContract("Functions Router", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return functions_router.NewFunctionsRouter(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsRouter{ - client: e.client, - instance: instance.(*functions_router.FunctionsRouter), - address: common.HexToAddress(addr), - l: e.l, - }, err -} - -// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance -func (e *EthereumContractLoader) LoadFunctionsLoadTestClient(addr string) (FunctionsLoadTestClient, error) { - instance, err := e.client.LoadContract("FunctionsLoadTestClient", common.HexToAddress(addr), func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return functions_load_test_client.NewFunctionsLoadTestClient(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumFunctionsLoadTestClient{ - client: e.client, - instance: instance.(*functions_load_test_client.FunctionsLoadTestClient), - address: common.HexToAddress(addr), - }, err -} - -// LoadOperatorContract returns deployed on given address Operator contract instance -func (e *EthereumContractLoader) LoadOperatorContract(address common.Address) (Operator, error) { - instance, err := e.client.LoadContract("Operator", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return operator_wrapper.NewOperator(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumOperator{ - address: address, - client: e.client, - operator: instance.(*operator_wrapper.Operator), - l: e.l, - }, err -} - -// LoadAuthorizedForwarder returns deployed on given address AuthorizedForwarder contract instance -func (e *EthereumContractLoader) LoadAuthorizedForwarder(address common.Address) (AuthorizedForwarder, error) { - instance, err := e.client.LoadContract("AuthorizedForwarder", address, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return authorized_forwarder.NewAuthorizedForwarder(address, backend) - }) - if err != nil { - return nil, err - } - return &LegacyEthereumAuthorizedForwarder{ - address: address, - client: e.client, - authorizedForwarder: instance.(*authorized_forwarder.AuthorizedForwarder), - }, err -} - -// LoadMercuryVerifier returns Verifier contract deployed on given address -func (e *EthereumContractLoader) LoadMercuryVerifier(addr common.Address) (MercuryVerifier, error) { - instance, err := e.client.LoadContract("Mercury Verifier", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return verifier.NewVerifier(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifier{ - client: e.client, - instance: instance.(*verifier.Verifier), - address: addr, - }, err -} - -// LoadMercuryVerifierProxy returns VerifierProxy contract deployed on given address -func (e *EthereumContractLoader) LoadMercuryVerifierProxy(addr common.Address) (MercuryVerifierProxy, error) { - instance, err := e.client.LoadContract("Mercury Verifier Proxy", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return verifier_proxy.NewVerifierProxy(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryVerifierProxy{ - client: e.client, - instance: instance.(*verifier_proxy.VerifierProxy), - address: addr, - }, err -} - -func (e *EthereumContractLoader) LoadMercuryFeeManager(addr common.Address) (MercuryFeeManager, error) { - instance, err := e.client.LoadContract("Mercury Fee Manager", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return fee_manager.NewFeeManager(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryFeeManager{ - client: e.client, - instance: instance.(*fee_manager.FeeManager), - address: addr, - }, err -} - -func (e *EthereumContractLoader) LoadMercuryRewardManager(addr common.Address) (MercuryRewardManager, error) { - instance, err := e.client.LoadContract("Mercury Reward Manager", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return reward_manager.NewRewardManager(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumMercuryRewardManager{ - client: e.client, - instance: instance.(*reward_manager.RewardManager), - address: addr, - }, err -} - -func (e *EthereumContractLoader) LoadWERC20Mock(addr common.Address) (WERC20Mock, error) { - instance, err := e.client.LoadContract("WERC20 Mock", addr, func( - address common.Address, - backend bind.ContractBackend, - ) (interface{}, error) { - return werc20_mock.NewWERC20Mock(address, backend) - }) - if err != nil { - return nil, err - } - return &EthereumWERC20Mock{ - client: e.client, - instance: instance.(*werc20_mock.WERC20Mock), - address: addr, - }, err -} - -func LoadVRFCoordinatorV2_5(seth *seth.Client, addr string) (VRFCoordinatorV2_5, error) { - address := common.HexToAddress(addr) - abi, err := vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.GetAbi() - if err != nil { - return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to get VRFCoordinatorV2_5 ABI: %w", err) - } - seth.ContractStore.AddABI("VRFCoordinatorV2_5", *abi) - seth.ContractStore.AddBIN("VRFCoordinatorV2_5", common.FromHex(vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.Bin)) - - contract, err := vrf_coordinator_v2_5.NewVRFCoordinatorV25(address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to instantiate VRFCoordinatorV2_5 instance: %w", err) - } - - return &EthereumVRFCoordinatorV2_5{ - client: seth, - address: address, - coordinator: contract, - }, nil -} - -func LoadBlockHashStore(seth *seth.Client, addr string) (BlockHashStore, error) { - address := common.HexToAddress(addr) - abi, err := blockhash_store.BlockhashStoreMetaData.GetAbi() - if err != nil { - return &EthereumBlockhashStore{}, fmt.Errorf("failed to get BlockHashStore ABI: %w", err) - } - seth.ContractStore.AddABI("BlockHashStore", *abi) - seth.ContractStore.AddBIN("BlockHashStore", common.FromHex(blockhash_store.BlockhashStoreMetaData.Bin)) - - contract, err := blockhash_store.NewBlockhashStore(address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumBlockhashStore{}, fmt.Errorf("failed to instantiate BlockHashStore instance: %w", err) - } - - return &EthereumBlockhashStore{ - client: seth, - address: &address, - blockHashStore: contract, - }, nil -} - -func LoadVRFv2PlusLoadTestConsumer(seth *seth.Client, addr string) (VRFv2PlusLoadTestConsumer, error) { - address := common.HexToAddress(addr) - abi, err := vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.GetAbi() - if err != nil { - return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to get VRFV2PlusLoadTestWithMetrics ABI: %w", err) - } - seth.ContractStore.AddABI("VRFV2PlusLoadTestWithMetrics", *abi) - seth.ContractStore.AddBIN("VRFV2PlusLoadTestWithMetrics", common.FromHex(vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.Bin)) - - contract, err := vrf_v2plus_load_test_with_metrics.NewVRFV2PlusLoadTestWithMetrics(address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to instantiate VRFV2PlusLoadTestWithMetrics instance: %w", err) - } - - return &EthereumVRFv2PlusLoadTestConsumer{ - client: seth, - address: address, - consumer: contract, - }, nil -} diff --git a/integration-tests/contracts/contract_models.go b/integration-tests/contracts/contract_models.go index b3b279766d..f61912bc3d 100644 --- a/integration-tests/contracts/contract_models.go +++ b/integration-tests/contracts/contract_models.go @@ -83,6 +83,16 @@ type LinkToken interface { TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) TransferAndCallFromKey(to string, amount *big.Int, data []byte, keyNum int) (*types.Transaction, error) Name(context.Context) (string, error) + Decimals() uint +} + +type WETHToken interface { + Address() string + Approve(to string, amount *big.Int) error + Transfer(to string, amount *big.Int) error + BalanceOf(ctx context.Context, addr string) (*big.Int, error) + Name(context.Context) (string, error) + Decimals() uint } type OffchainOptions struct { @@ -222,6 +232,13 @@ type MockETHLINKFeed interface { LatestRoundDataUpdatedAt() (*big.Int, error) } +type MockETHUSDFeed interface { + Address() string + LatestRoundData() (*big.Int, error) + LatestRoundDataUpdatedAt() (*big.Int, error) + Decimals() uint +} + type MockGasFeed interface { Address() string } diff --git a/integration-tests/contracts/ethereum/KeeperRegistryVersions.go b/integration-tests/contracts/ethereum/KeeperRegistryVersions.go index 4aee8d75d2..d5d0c2edea 100644 --- a/integration-tests/contracts/ethereum/KeeperRegistryVersions.go +++ b/integration-tests/contracts/ethereum/KeeperRegistryVersions.go @@ -19,4 +19,5 @@ const ( RegistryVersion_2_0 RegistryVersion_2_1 RegistryVersion_2_2 + RegistryVersion_2_3 ) diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index ec61ad6818..ebe99da2d9 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -3,2117 +3,1391 @@ package contracts import ( "context" "encoding/hex" + "errors" "fmt" "math/big" "strings" "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - contractsethereum "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/weth9_wrapper" + contractsethereum "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flags_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_billing_registry_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/functions_oracle_events_mock" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper_mock" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" iregistry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" iregistry21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_aggregator_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/fee_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/reward_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/verifier_proxy" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/werc20_mock" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" ) -// LegacyEthereumOracle oracle for "directrequest" job tests -type LegacyEthereumOracle struct { - address *common.Address - client blockchain.EVMClient - oracle *oracle_wrapper.Oracle -} - -func (e *LegacyEthereumOracle) Address() string { - return e.address.Hex() -} - -func (e *LegacyEthereumOracle) Fund(ethAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ - To: e.address, - }) - if err != nil { - return err - } - return e.client.Fund(e.address.Hex(), ethAmount, gasEstimates) -} - -// SetFulfillmentPermission sets fulfillment permission for particular address -func (e *LegacyEthereumOracle) SetFulfillmentPermission(address string, allowed bool) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.oracle.SetFulfillmentPermission(opts, common.HexToAddress(address), allowed) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) -} - -// LegacyEthereumAPIConsumer API consumer for job type "directrequest" tests -type LegacyEthereumAPIConsumer struct { - address *common.Address - client blockchain.EVMClient - consumer *test_api_consumer_wrapper.TestAPIConsumer -} - -func (e *LegacyEthereumAPIConsumer) Address() string { - return e.address.Hex() -} - -func (e *LegacyEthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - return e.consumer.CurrentRoundID(opts) -} - -func (e *LegacyEthereumAPIConsumer) Fund(ethAmount *big.Float) error { - gasEstimates, err := e.client.EstimateGas(ethereum.CallMsg{ - To: e.address, - }) - if err != nil { - return err - } - return e.client.Fund(e.address.Hex(), ethAmount, gasEstimates) -} - -func (e *LegacyEthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - data, err := e.consumer.Data(opts) - if err != nil { - return nil, err - } - return data, nil -} - -// CreateRequestTo creates request to an oracle for particular jobID with params -func (e *LegacyEthereumAPIConsumer) CreateRequestTo( - oracleAddr string, - jobID [32]byte, - payment *big.Int, - url string, - path string, - times *big.Int, -) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.consumer.CreateRequestTo(opts, common.HexToAddress(oracleAddr), jobID, payment, url, path, times) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) -} - -// EthereumStaking -type EthereumStaking struct { - client blockchain.EVMClient - staking *eth_contracts.Staking - address *common.Address -} - -func (f *EthereumStaking) Address() string { - return f.address.Hex() -} - -// Fund sends specified currencies to the contract -func (f *EthereumStaking) Fund(ethAmount *big.Float) error { - gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{ - To: f.address, - }) - if err != nil { - return err - } - return f.client.Fund(f.address.Hex(), ethAmount, gasEstimates) -} - -func (f *EthereumStaking) AddOperators(operators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.AddOperators(opts, operators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -func (f *EthereumStaking) RemoveOperators(operators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.RemoveOperators(opts, operators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +// OCRv2Config represents the config for the OCRv2 contract +type OCRv2Config struct { + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + TypedOnchainConfig21 i_keeper_registry_master_wrapper_2_1.IAutomationV21PlusCommonOnchainConfigLegacy + TypedOnchainConfig22 i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig + TypedOnchainConfig23 i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig + OffchainConfigVersion uint64 + OffchainConfig []byte + BillingTokens []common.Address + BillingConfigs []i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23BillingConfig } -func (f *EthereumStaking) SetFeedOperators(operators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.SetFeedOperators(opts, operators) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +type EthereumFunctionsLoadStats struct { + LastRequestID string + LastResponse string + LastError string + Total uint32 + Succeeded uint32 + Errored uint32 + Empty uint32 } -func (f *EthereumStaking) RaiseAlert() error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.RaiseAlert(opts) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func Bytes32ToSlice(a [32]byte) (r []byte) { + r = append(r, a[:]...) + return } -func (f *EthereumStaking) Start(amount *big.Int, initialRewardRate *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.Start(opts, amount, initialRewardRate) - if err != nil { - return err +// DefaultOffChainAggregatorOptions returns some base defaults for deploying an OCR contract +func DefaultOffChainAggregatorOptions() OffchainOptions { + return OffchainOptions{ + MaximumGasPrice: uint32(3000), + ReasonableGasPrice: uint32(10), + MicroLinkPerEth: uint32(500), + LinkGweiPerObservation: uint32(500), + LinkGweiPerTransmission: uint32(500), + MinimumAnswer: big.NewInt(1), + MaximumAnswer: big.NewInt(50000000000000000), + Decimals: 8, + Description: "Test OCR", + } +} + +// DefaultOffChainAggregatorConfig returns some base defaults for configuring an OCR contract +func DefaultOffChainAggregatorConfig(numberNodes int) OffChainAggregatorConfig { + if numberNodes <= 4 { + log.Err(fmt.Errorf("insufficient number of nodes (%d) supplied for OCR, need at least 5", numberNodes)). + Int("Number Chainlink Nodes", numberNodes). + Msg("You likely need more chainlink nodes to properly configure OCR, try 5 or more.") + } + s := []int{1} + // First node's stage already inputted as a 1 in line above, so numberNodes-1. + for i := 0; i < numberNodes-1; i++ { + s = append(s, 2) + } + return OffChainAggregatorConfig{ + AlphaPPB: 1, + DeltaC: time.Minute * 60, + DeltaGrace: time.Second * 12, + DeltaProgress: time.Second * 35, + DeltaStage: time.Second * 60, + DeltaResend: time.Second * 17, + DeltaRound: time.Second * 30, + RMax: 6, + S: s, + N: numberNodes, + F: 1, + OracleIdentities: []ocrConfigHelper.OracleIdentityExtra{}, } - return f.client.ProcessTransaction(tx) } -func (f *EthereumStaking) SetMerkleRoot(newMerkleRoot [32]byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.staking.SetMerkleRoot(opts, newMerkleRoot) - if err != nil { - return err +func ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkK8sClient) []ChainlinkNodeWithKeysAndAddress { + var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) + for i, node := range k8sNodes { + nodesAsInterface[i] = node } - return f.client.ProcessTransaction(tx) -} - -// EthereumFunctionsOracleEventsMock represents the basic events mock contract -type EthereumFunctionsOracleEventsMock struct { - client blockchain.EVMClient - eventsMock *functions_oracle_events_mock.FunctionsOracleEventsMock - address *common.Address -} - -func (f *EthereumFunctionsOracleEventsMock) Address() string { - return f.address.Hex() -} -func (f *EthereumFunctionsOracleEventsMock) OracleResponse(requestId [32]byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOracleResponse(opts, requestId) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return nodesAsInterface } -func (f *EthereumFunctionsOracleEventsMock) OracleRequest(requestId [32]byte, requestingContract common.Address, requestInitiator common.Address, subscriptionId uint64, subscriptionOwner common.Address, data []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOracleRequest(opts, requestId, requestingContract, requestInitiator, subscriptionId, subscriptionOwner, data) - if err != nil { - return err +func ChainlinkClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkClient) []ChainlinkNodeWithKeysAndAddress { + var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) + for i, node := range k8sNodes { + nodesAsInterface[i] = node } - return f.client.ProcessTransaction(tx) -} -func (f *EthereumFunctionsOracleEventsMock) UserCallbackError(requestId [32]byte, reason string) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitUserCallbackError(opts, requestId, reason) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return nodesAsInterface } -func (f *EthereumFunctionsOracleEventsMock) UserCallbackRawError(requestId [32]byte, lowLevelData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitUserCallbackRawError(opts, requestId, lowLevelData) - if err != nil { - return err +func V2OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregatorV2) []OffChainAggregatorWithRounds { + var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) + for i, contract := range contracts { + contractsAsInterface[i] = contract } - return f.client.ProcessTransaction(tx) -} - -// EthereumFunctionsBillingRegistryEventsMock represents the basic events mock contract -type EthereumFunctionsBillingRegistryEventsMock struct { - client blockchain.EVMClient - eventsMock *functions_billing_registry_events_mock.FunctionsBillingRegistryEventsMock - address *common.Address -} -func (f *EthereumFunctionsBillingRegistryEventsMock) Address() string { - return f.address.Hex() + return contractsAsInterface } -func (f *EthereumFunctionsBillingRegistryEventsMock) SubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionFunded(opts, subscriptionId, oldBalance, newBalance) - if err != nil { - return err +func V1OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregator) []OffChainAggregatorWithRounds { + var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) + for i, contract := range contracts { + contractsAsInterface[i] = contract } - return f.client.ProcessTransaction(tx) -} -func (f *EthereumFunctionsBillingRegistryEventsMock) BillingStart(requestId [32]byte, commitment functions_billing_registry_events_mock.FunctionsBillingRegistryEventsMockCommitment) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitBillingStart(opts, requestId, commitment) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return contractsAsInterface } -func (f *EthereumFunctionsBillingRegistryEventsMock) BillingEnd(requestId [32]byte, subscriptionId uint64, signerPayment *big.Int, transmitterPayment *big.Int, totalCost *big.Int, success bool) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitBillingEnd(opts, requestId, subscriptionId, signerPayment, transmitterPayment, totalCost, success) - if err != nil { - return err +func GetRegistryContractABI(version contractsethereum.KeeperRegistryVersion) (*abi.ABI, error) { + var ( + contractABI *abi.ABI + err error + ) + switch version { + case contractsethereum.RegistryVersion_1_0, contractsethereum.RegistryVersion_1_1: + contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_1_2: + contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_1_3: + contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_2_0: + contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() + case contractsethereum.RegistryVersion_2_1: + contractABI, err = iregistry21.IKeeperRegistryMasterMetaData.GetAbi() + case contractsethereum.RegistryVersion_2_2: + contractABI, err = iregistry22.IAutomationRegistryMasterMetaData.GetAbi() + default: + contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() } - return f.client.ProcessTransaction(tx) -} -// LegacyEthereumStakingEventsMock represents the basic events mock contract -type LegacyEthereumStakingEventsMock struct { - client blockchain.EVMClient - eventsMock *eth_contracts.StakingEventsMock - address *common.Address -} - -func (f *LegacyEthereumStakingEventsMock) Address() string { - return f.address.Hex() -} - -func (f *LegacyEthereumStakingEventsMock) MaxCommunityStakeAmountIncreased(maxStakeAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitMaxCommunityStakeAmountIncreased(opts, maxStakeAmount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return contractABI, err } -func (f *LegacyEthereumStakingEventsMock) PoolSizeIncreased(maxPoolSize *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitPoolSizeIncreased(opts, maxPoolSize) - if err != nil { - return err +// DefaultFluxAggregatorOptions produces some basic defaults for a flux aggregator contract +func DefaultFluxAggregatorOptions() FluxAggregatorOptions { + return FluxAggregatorOptions{ + PaymentAmount: big.NewInt(1), + Timeout: uint32(30), + MinSubValue: big.NewInt(0), + MaxSubValue: big.NewInt(1000000000000), + Decimals: uint8(0), + Description: "Test Flux Aggregator", } - return f.client.ProcessTransaction(tx) } -func (f *LegacyEthereumStakingEventsMock) MaxOperatorStakeAmountIncreased(maxStakeAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitMaxOperatorStakeAmountIncreased(opts, maxStakeAmount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +// EthereumOffchainAggregator represents the offchain aggregation contract +type EthereumOffchainAggregator struct { + client *seth.Client + ocr *offchainaggregator.OffchainAggregator + address *common.Address + l zerolog.Logger } -func (f *LegacyEthereumStakingEventsMock) RewardInitialized(rate *big.Int, available *big.Int, startTimestamp *big.Int, endTimestamp *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRewardInitialized(opts, rate, available, startTimestamp, endTimestamp) +func LoadOffchainAggregator(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { + abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return f.client.ProcessTransaction(tx) -} + seth.ContractStore.AddABI("OffChainAggregator", *abi) + seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) -func (f *LegacyEthereumStakingEventsMock) AlertRaised(alerter common.Address, roundId *big.Int, rewardAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitAlertRaised(opts, alerter, roundId, rewardAmount) + ocr, err := offchainaggregator.NewOffchainAggregator(contractAddress, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumStakingEventsMock) Staked(staker common.Address, newStake *big.Int, totalStake *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitStaked(opts, staker, newStake, totalStake) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return EthereumOffchainAggregator{ + client: seth, + ocr: ocr, + address: &contractAddress, + l: l, + }, nil } -func (f *LegacyEthereumStakingEventsMock) OperatorAdded(operator common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitOperatorAdded(opts, operator) +func DeployOffchainAggregator(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregator, error) { + abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumStakingEventsMock) OperatorRemoved(operator common.Address, amount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) + ocrDeploymentData, err := seth.DeployContract( + seth.NewTXOpts(), + "OffChainAggregator", + *abi, + common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin), + offchainOptions.MaximumGasPrice, + offchainOptions.ReasonableGasPrice, + offchainOptions.MicroLinkPerEth, + offchainOptions.LinkGweiPerObservation, + offchainOptions.LinkGweiPerTransmission, + linkTokenAddress, + offchainOptions.MinimumAnswer, + offchainOptions.MaximumAnswer, + offchainOptions.BillingAccessController, + offchainOptions.RequesterAccessController, + offchainOptions.Decimals, + offchainOptions.Description) if err != nil { - return err - } - tx, err := f.eventsMock.EmitOperatorRemoved(opts, operator, amount) - if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("OCR instance deployment have failed: %w", err) } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumStakingEventsMock) FeedOperatorsSet(feedOperators []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitFeedOperatorsSet(opts, feedOperators) + ocr, err := offchainaggregator.NewOffchainAggregator(ocrDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return f.client.ProcessTransaction(tx) -} - -// EthereumOffchainAggregatorEventsMock represents the basic events mock contract -type EthereumOffchainAggregatorEventsMock struct { - client blockchain.EVMClient - eventsMock *eth_contracts.OffchainAggregatorEventsMock - address *common.Address -} -func (f *EthereumOffchainAggregatorEventsMock) Address() string { - return f.address.Hex() + return EthereumOffchainAggregator{ + client: seth, + ocr: ocr, + address: &ocrDeploymentData.Address, + l: l, + }, nil } -func (f *EthereumOffchainAggregatorEventsMock) ConfigSet(previousConfigBlockNumber uint32, configCount uint64, signers []common.Address, transmitters []common.Address, threshold uint8, encodedConfigVersion uint64, encoded []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err +// SetPayees sets wallets for the contract to pay out to? +func (o *EthereumOffchainAggregator) SetPayees( + transmitters, payees []string, +) error { + var transmittersAddr, payeesAddr []common.Address + for _, tr := range transmitters { + transmittersAddr = append(transmittersAddr, common.HexToAddress(tr)) } - tx, err := f.eventsMock.EmitConfigSet(opts, previousConfigBlockNumber, configCount, signers, transmitters, threshold, encodedConfigVersion, encoded) - if err != nil { - return err + for _, p := range payees { + payeesAddr = append(payeesAddr, common.HexToAddress(p)) } - return f.client.ProcessTransaction(tx) -} -func (f *EthereumOffchainAggregatorEventsMock) NewTransmission(aggregatorRoundId uint32, answer *big.Int, transmitter common.Address, observations []*big.Int, observers []byte, rawReportContext [32]byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitNewTransmission(opts, aggregatorRoundId, answer, transmitter, observations, observers, rawReportContext) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} + o.l.Info(). + Str("Transmitters", fmt.Sprintf("%v", transmitters)). + Str("Payees", fmt.Sprintf("%v", payees)). + Str("OCR Address", o.Address()). + Msg("Setting OCR Payees") -// LegacyEthereumKeeperRegistry11Mock represents the basic keeper registry 1.1 mock contract -type LegacyEthereumKeeperRegistry11Mock struct { - client blockchain.EVMClient - registryMock *keeper_registry_wrapper1_1_mock.KeeperRegistryMock - address *common.Address + _, err := o.client.Decode(o.ocr.SetPayees(o.client.NewTXOpts(), transmittersAddr, payeesAddr)) + return err } -func (f *LegacyEthereumKeeperRegistry11Mock) Address() string { - return f.address.Hex() -} +// SetConfig sets the payees and the offchain reporting protocol configuration +func (o *EthereumOffchainAggregator) SetConfig( + chainlinkNodes []ChainlinkNodeWithKeysAndAddress, + ocrConfig OffChainAggregatorConfig, + transmitters []common.Address, +) error { + // Gather necessary addresses and keys from our chainlink nodes to properly configure the OCR contract + log.Info().Str("Contract Address", o.address.Hex()).Msg("Configuring OCR Contract") + for i, node := range chainlinkNodes { + ocrKeys, err := node.MustReadOCRKeys() + if err != nil { + return err + } + if len(ocrKeys.Data) == 0 { + return fmt.Errorf("no OCR keys found for node %v", node) + } + primaryOCRKey := ocrKeys.Data[0] + p2pKeys, err := node.MustReadP2PKeys() + if err != nil { + return err + } + primaryP2PKey := p2pKeys.Data[0] -func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepPerformed(id *big.Int, success bool, from common.Address, payment *big.Int, performData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitUpkeepPerformed(opts, id, success, from, payment, performData) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} + // Need to convert the key representations + var onChainSigningAddress [20]byte + var configPublicKey [32]byte + offchainSigningAddress, err := hex.DecodeString(primaryOCRKey.Attributes.OffChainPublicKey) + if err != nil { + return err + } + decodeConfigKey, err := hex.DecodeString(primaryOCRKey.Attributes.ConfigPublicKey) + if err != nil { + return err + } -func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepCanceled(id *big.Int, atBlockHeight uint64) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitUpkeepCanceled(opts, id, atBlockHeight) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} + // https://stackoverflow.com/questions/8032170/how-to-assign-string-to-bytes-array + copy(onChainSigningAddress[:], common.HexToAddress(primaryOCRKey.Attributes.OnChainSigningAddress).Bytes()) + copy(configPublicKey[:], decodeConfigKey) -func (f *LegacyEthereumKeeperRegistry11Mock) EmitFundsWithdrawn(id *big.Int, amount *big.Int, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitFundsWithdrawn(opts, id, amount, to) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} + oracleIdentity := ocrConfigHelper.OracleIdentity{ + TransmitAddress: transmitters[i], + OnChainSigningAddress: onChainSigningAddress, + PeerID: primaryP2PKey.Attributes.PeerID, + OffchainPublicKey: offchainSigningAddress, + } + oracleIdentityExtra := ocrConfigHelper.OracleIdentityExtra{ + OracleIdentity: oracleIdentity, + SharedSecretEncryptionPublicKey: ocrTypes.SharedSecretEncryptionPublicKey(configPublicKey), + } -func (f *LegacyEthereumKeeperRegistry11Mock) EmitKeepersUpdated(keepers []common.Address, payees []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitKeepersUpdated(opts, keepers, payees) - if err != nil { - return err + ocrConfig.OracleIdentities = append(ocrConfig.OracleIdentities, oracleIdentityExtra) } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepRegistered(id *big.Int, executeGas uint32, admin common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitUpkeepRegistered(opts, id, executeGas, admin) + signers, transmitters, threshold, encodedConfigVersion, encodedConfig, err := ocrConfigHelper.ContractSetConfigArgs( + ocrConfig.DeltaProgress, + ocrConfig.DeltaResend, + ocrConfig.DeltaRound, + ocrConfig.DeltaGrace, + ocrConfig.DeltaC, + ocrConfig.AlphaPPB, + ocrConfig.DeltaStage, + ocrConfig.RMax, + ocrConfig.S, + ocrConfig.OracleIdentities, + ocrConfig.F, + ) if err != nil { return err } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumKeeperRegistry11Mock) EmitFundsAdded(id *big.Int, from common.Address, amount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.EmitFundsAdded(opts, id, from, amount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + // fails with error setting OCR config for contract '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82': both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified + // but we only have gasPrice set... It also fails with the same error when we enable EIP-1559 + // fails when we wait for it to be minted, inside the wrapper there's no error when we call it, so it must be something inside smart contract + // that's reverting it and maybe the error message is completely off + _, err = o.client.Decode(o.ocr.SetConfig(o.client.NewTXOpts(), signers, transmitters, threshold, encodedConfigVersion, encodedConfig)) + return err } -func (f *LegacyEthereumKeeperRegistry11Mock) SetUpkeepCount(_upkeepCount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetUpkeepCount(opts, _upkeepCount) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +// RequestNewRound requests the OCR contract to create a new round +func (o *EthereumOffchainAggregator) RequestNewRound() error { + o.l.Info().Str("Contract Address", o.address.Hex()).Msg("New OCR round requested") + _, err := o.client.Decode(o.ocr.RequestNewRound(o.client.NewTXOpts())) + return err } -func (f *LegacyEthereumKeeperRegistry11Mock) SetCanceledUpkeepList(_canceledUpkeepList []*big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetCanceledUpkeepList(opts, _canceledUpkeepList) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +// GetLatestAnswer returns the latest answer from the OCR contract +func (o *EthereumOffchainAggregator) GetLatestAnswer(ctx context.Context) (*big.Int, error) { + return o.ocr.LatestAnswer(&bind.CallOpts{ + From: o.client.Addresses[0], + Context: ctx, + }) } -func (f *LegacyEthereumKeeperRegistry11Mock) SetKeeperList(_keepers []common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetKeeperList(opts, _keepers) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func (o *EthereumOffchainAggregator) Address() string { + return o.address.Hex() } -func (f *LegacyEthereumKeeperRegistry11Mock) SetConfig(_paymentPremiumPPB uint32, _flatFeeMicroLink uint32, _blockCountPerTurn *big.Int, _checkGasLimit uint32, _stalenessSeconds *big.Int, _gasCeilingMultiplier uint16, _fallbackGasPrice *big.Int, _fallbackLinkPrice *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetConfig(opts, _paymentPremiumPPB, _flatFeeMicroLink, _blockCountPerTurn, _checkGasLimit, _stalenessSeconds, _gasCeilingMultiplier, _fallbackGasPrice, _fallbackLinkPrice) +// GetLatestRound returns data from the latest round +func (o *EthereumOffchainAggregator) GetLatestRound(ctx context.Context) (*RoundData, error) { + roundData, err := o.ocr.LatestRoundData(&bind.CallOpts{ + From: o.client.Addresses[0], + Context: ctx, + }) if err != nil { - return err + return nil, err } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumKeeperRegistry11Mock) SetUpkeep(id *big.Int, _target common.Address, _executeGas uint32, _balance *big.Int, _admin common.Address, _maxValidBlocknumber uint64, _lastKeeper common.Address, _checkData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetUpkeep(opts, id, _target, _executeGas, _balance, _admin, _maxValidBlocknumber, _lastKeeper, _checkData) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return &RoundData{ + RoundId: roundData.RoundId, + Answer: roundData.Answer, + AnsweredInRound: roundData.AnsweredInRound, + StartedAt: roundData.StartedAt, + UpdatedAt: roundData.UpdatedAt, + }, err } -func (f *LegacyEthereumKeeperRegistry11Mock) SetMinBalance(id *big.Int, minBalance *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetMinBalance(opts, id, minBalance) +func (o *EthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { + data, err := o.ocr.LatestRoundData(o.client.NewCallOpts()) if err != nil { - return err + return nil, err } - return f.client.ProcessTransaction(tx) + return data.UpdatedAt, nil } -func (f *LegacyEthereumKeeperRegistry11Mock) SetCheckUpkeepData(id *big.Int, performData []byte, maxLinkPayment *big.Int, gasLimit *big.Int, adjustedGasWei *big.Int, linkEth *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetCheckUpkeepData(opts, id, performData, maxLinkPayment, gasLimit, adjustedGasWei, linkEth) +// GetRound retrieves an OCR round by the round ID +func (o *EthereumOffchainAggregator) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { + roundData, err := o.ocr.GetRoundData(&bind.CallOpts{ + From: o.client.Addresses[0], + Context: ctx, + }, roundID) if err != nil { - return err + return nil, err } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumKeeperRegistry11Mock) SetPerformUpkeepSuccess(id *big.Int, success bool) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registryMock.SetPerformUpkeepSuccess(opts, id, success) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return &RoundData{ + RoundId: roundData.RoundId, + Answer: roundData.Answer, + AnsweredInRound: roundData.AnsweredInRound, + StartedAt: roundData.StartedAt, + UpdatedAt: roundData.UpdatedAt, + }, nil } -// LegacyEthereumKeeperRegistrar12Mock represents the basic keeper registrar 1.2 mock contract -type LegacyEthereumKeeperRegistrar12Mock struct { - client blockchain.EVMClient - registrarMock *keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock - address *common.Address +// ParseEventAnswerUpdated parses the log for event AnswerUpdated +func (o *EthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { + return o.ocr.ParseAnswerUpdated(eventLog) } -func (f *LegacyEthereumKeeperRegistrar12Mock) Address() string { - return f.address.Hex() +// LegacyEthereumOperatorFactory represents operator factory contract +type EthereumOperatorFactory struct { + address *common.Address + client *seth.Client + operatorFactory *operator_factory.OperatorFactory } -func (f *LegacyEthereumKeeperRegistrar12Mock) EmitRegistrationRequested(hash [32]byte, name string, encryptedEmail []byte, upkeepContract common.Address, gasLimit uint32, adminAddress common.Address, checkData []byte, amount *big.Int, source uint8) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) +func DeployEthereumOperatorFactory(seth *seth.Client, linkTokenAddress common.Address) (EthereumOperatorFactory, error) { + abi, err := operator_factory.OperatorFactoryMetaData.GetAbi() if err != nil { - return err + return EthereumOperatorFactory{}, fmt.Errorf("failed to get OperatorFactory ABI: %w", err) } - tx, err := f.registrarMock.EmitRegistrationRequested(opts, hash, name, encryptedEmail, upkeepContract, gasLimit, adminAddress, checkData, amount, source) + operatorData, err := seth.DeployContract(seth.NewTXOpts(), "OperatorFactory", *abi, common.FromHex(operator_factory.OperatorFactoryMetaData.Bin), linkTokenAddress) if err != nil { - return err + return EthereumOperatorFactory{}, fmt.Errorf("OperatorFactory instance deployment have failed: %w", err) } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumKeeperRegistrar12Mock) EmitRegistrationApproved(hash [32]byte, displayName string, upkeepId *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registrarMock.EmitRegistrationApproved(opts, hash, displayName, upkeepId) + operatorFactory, err := operator_factory.NewOperatorFactory(operatorData.Address, seth.Client) if err != nil { - return err + return EthereumOperatorFactory{}, fmt.Errorf("failed to instantiate OperatorFactory instance: %w", err) } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumKeeperRegistrar12Mock) SetRegistrationConfig(_autoApproveConfigType uint8, _autoApproveMaxAllowed uint32, _approvedCount uint32, _keeperRegistry common.Address, _minLINKJuels *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.registrarMock.SetRegistrationConfig(opts, _autoApproveConfigType, _autoApproveMaxAllowed, _approvedCount, _keeperRegistry, _minLINKJuels) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return EthereumOperatorFactory{ + address: &operatorData.Address, + client: seth, + operatorFactory: operatorFactory, + }, nil } -// LegacyEthereumKeeperGasWrapperMock represents the basic keeper gas wrapper mock contract -type LegacyEthereumKeeperGasWrapperMock struct { - client blockchain.EVMClient - gasWrapperMock *gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock - address *common.Address +func (e *EthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { + return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) } -func (f *LegacyEthereumKeeperGasWrapperMock) Address() string { - return f.address.Hex() +func (e *EthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { + return e.operatorFactory.ParseOperatorCreated(eventLog) } -func (f *LegacyEthereumKeeperGasWrapperMock) SetMeasureCheckGasResult(result bool, payload []byte, gas *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.gasWrapperMock.SetMeasureCheckGasResult(opts, result, payload, gas) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func (e *EthereumOperatorFactory) Address() string { + return e.address.Hex() } -// LegacyEthereumFunctionsV1EventsMock represents the basic functions v1 events mock contract -type LegacyEthereumFunctionsV1EventsMock struct { - client blockchain.EVMClient - eventsMock *functions_v1_events_mock.FunctionsV1EventsMock - address *common.Address +func (e *EthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return e.operatorFactory.DeployNewOperatorAndForwarder(e.client.NewTXOpts()) } -func (f *LegacyEthereumFunctionsV1EventsMock) Address() string { - return f.address.Hex() +// EthereumOperator represents operator contract +type EthereumOperator struct { + address *common.Address + client *seth.Client + operator *operator_wrapper.Operator + l zerolog.Logger } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestProcessed(requestId [32]byte, subscriptionId uint64, totalCostJuels *big.Int, transmitter common.Address, resultCode uint8, response []byte, errByte []byte, callbackReturnData []byte) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRequestProcessed(opts, requestId, subscriptionId, totalCostJuels, transmitter, resultCode, response, errByte, callbackReturnData) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} +func LoadEthereumOperator(logger zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOperator, error) { -func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestStart(requestId [32]byte, donId [32]byte, subscriptionId uint64, subscriptionOwner common.Address, requestingContract common.Address, requestInitiator common.Address, data []byte, dataVersion uint16, callbackGasLimit uint32, estimatedTotalCostJuels *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) + abi, err := operator_wrapper.OperatorMetaData.GetAbi() if err != nil { - return err - } - tx, err := f.eventsMock.EmitRequestStart(opts, requestId, donId, subscriptionId, subscriptionOwner, requestingContract, requestInitiator, data, dataVersion, callbackGasLimit, estimatedTotalCostJuels) - if err != nil { - return err + return EthereumOperator{}, err } - return f.client.ProcessTransaction(tx) -} + seth.ContractStore.AddABI("EthereumOperator", *abi) + seth.ContractStore.AddBIN("EthereumOperator", common.FromHex(operator_wrapper.OperatorMetaData.Bin)) -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCanceled(subscriptionId uint64, fundsRecipient common.Address, fundsAmount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionCanceled(opts, subscriptionId, fundsRecipient, fundsAmount) + operator, err := operator_wrapper.NewOperator(contractAddress, seth.Client) if err != nil { - return err + return EthereumOperator{}, err } - return f.client.ProcessTransaction(tx) -} -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionConsumerAdded(subscriptionId uint64, consumer common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionConsumerAdded(opts, subscriptionId, consumer) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) + return EthereumOperator{ + address: &contractAddress, + client: seth, + operator: operator, + l: logger, + }, nil } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionConsumerRemoved(subscriptionId uint64, consumer common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionConsumerRemoved(opts, subscriptionId, consumer) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func (e *EthereumOperator) Address() string { + return e.address.Hex() } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId uint64, owner common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionCreated(opts, subscriptionId, owner) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func (e *EthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { + e.l.Info(). + Str("ForwardersAddresses", fmt.Sprint(forwarders)). + Str("EoaAddresses", fmt.Sprint(eoa)). + Msg("Accepting Authorized Receivers") + _, err := e.client.Decode(e.operator.AcceptAuthorizedReceivers(e.client.NewTXOpts(), forwarders, eoa)) + return err } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionFunded(opts, subscriptionId, oldBalance, newBalance) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +// EthereumAuthorizedForwarder represents authorized forwarder contract +type EthereumAuthorizedForwarder struct { + address *common.Address + client *seth.Client + authorizedForwarder *authorized_forwarder.AuthorizedForwarder } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferred(subscriptionId uint64, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionOwnerTransferred(opts, subscriptionId, from, to) +func LoadEthereumAuthorizedForwarder(seth *seth.Client, contractAddress common.Address) (EthereumAuthorizedForwarder, error) { + abi, err := authorized_forwarder.AuthorizedForwarderMetaData.GetAbi() if err != nil { - return err + return EthereumAuthorizedForwarder{}, err } - return f.client.ProcessTransaction(tx) -} + seth.ContractStore.AddABI("AuthorizedForwarder", *abi) + seth.ContractStore.AddBIN("AuthorizedForwarder", common.FromHex(authorized_forwarder.AuthorizedForwarderMetaData.Bin)) -func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferRequested(subscriptionId uint64, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) + authorizedForwarder, err := authorized_forwarder.NewAuthorizedForwarder(contractAddress, seth.Client) if err != nil { - return err - } - tx, err := f.eventsMock.EmitSubscriptionOwnerTransferRequested(opts, subscriptionId, from, to) - if err != nil { - return err + return EthereumAuthorizedForwarder{}, fmt.Errorf("failed to instantiate AuthorizedForwarder instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumAuthorizedForwarder{ + address: &contractAddress, + client: seth, + authorizedForwarder: authorizedForwarder, + }, nil } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestNotProcessed(requestId [32]byte, coordinator common.Address, transmitter common.Address, resultCode uint8) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.eventsMock.EmitRequestNotProcessed(opts, requestId, coordinator, transmitter, resultCode) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +// Owner return authorized forwarder owner address +func (e *EthereumAuthorizedForwarder) Owner(_ context.Context) (string, error) { + owner, err := e.authorizedForwarder.Owner(e.client.NewCallOpts()) + + return owner.Hex(), err } -func (f *LegacyEthereumFunctionsV1EventsMock) EmitContractUpdated(id [32]byte, from common.Address, to common.Address) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err +func (e *EthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { + opts := &bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, } - tx, err := f.eventsMock.EmitContractUpdated(opts, id, from, to) + authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) if err != nil { - return err + return nil, err + } + var sendersAddrs []string + for _, o := range authorizedSenders { + sendersAddrs = append(sendersAddrs, o.Hex()) } - return f.client.ProcessTransaction(tx) + return sendersAddrs, nil } -// LegacyEthereumFluxAggregator represents the basic flux aggregation contract -type LegacyEthereumFluxAggregator struct { - client blockchain.EVMClient - fluxAggregator *flux_aggregator_wrapper.FluxAggregator - address *common.Address +func (e *EthereumAuthorizedForwarder) Address() string { + return e.address.Hex() } -func (f *LegacyEthereumFluxAggregator) Address() string { - return f.address.Hex() +type EthereumOffchainAggregatorV2 struct { + address *common.Address + client *seth.Client + contract *ocr2aggregator.OCR2Aggregator + l zerolog.Logger } -// Fund sends specified currencies to the contract -func (f *LegacyEthereumFluxAggregator) Fund(ethAmount *big.Float) error { - gasEstimates, err := f.client.EstimateGas(ethereum.CallMsg{ - To: f.address, - }) +func LoadOffChainAggregatorV2(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregatorV2, error) { + oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return f.client.Fund(f.address.Hex(), ethAmount, gasEstimates) -} + seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) -func (f *LegacyEthereumFluxAggregator) UpdateAvailableFunds() error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.fluxAggregator.UpdateAvailableFunds(opts) + ocr2, err := ocr2aggregator.NewOCR2Aggregator(contractAddress, seth.Client) if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumOffchainAggregatorV2{ + client: seth, + contract: ocr2, + address: &contractAddress, + l: l, + }, nil } -func (f *LegacyEthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - payment, err := f.fluxAggregator.PaymentAmount(opts) +func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregatorV2, error) { + oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() if err != nil { - return nil, err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) } - return payment, nil -} + seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) + seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) + + ocrDeploymentData2, err := seth.DeployContract(seth.NewTXOpts(), "OffChainAggregatorV2", *oAbi, common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin), + linkTokenAddress, + offchainOptions.MinimumAnswer, + offchainOptions.MaximumAnswer, + offchainOptions.BillingAccessController, + offchainOptions.RequesterAccessController, + offchainOptions.Decimals, + offchainOptions.Description, + ) -func (f *LegacyEthereumFluxAggregator) RequestNewRound(_ context.Context) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCR instance deployment have failed: %w", err) } - tx, err := f.fluxAggregator.RequestNewRound(opts) + + ocr2, err := ocr2aggregator.NewOCR2Aggregator(ocrDeploymentData2.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err + return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) } - return f.client.ProcessTransaction(tx) + + return EthereumOffchainAggregatorV2{ + client: seth, + contract: ocr2, + address: &ocrDeploymentData2.Address, + l: l, + }, nil } -// WatchSubmissionReceived subscribes to any submissions on a flux feed -func (f *LegacyEthereumFluxAggregator) WatchSubmissionReceived(ctx context.Context, eventChan chan<- *SubmissionEvent) error { - ethEventChan := make(chan *flux_aggregator_wrapper.FluxAggregatorSubmissionReceived) - sub, err := f.fluxAggregator.WatchSubmissionReceived(&bind.WatchOpts{}, ethEventChan, nil, nil, nil) - if err != nil { - return err - } - defer sub.Unsubscribe() - - for { - select { - case event := <-ethEventChan: - eventChan <- &SubmissionEvent{ - Contract: event.Raw.Address, - Submission: event.Submission, - Round: event.Round, - BlockNumber: event.Raw.BlockNumber, - Oracle: event.Oracle, - } - case err := <-sub.Err(): - return err - case <-ctx.Done(): - return nil - } - } +func (e *EthereumOffchainAggregatorV2) Address() string { + return e.address.Hex() } -func (f *LegacyEthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := f.fluxAggregator.SetRequesterPermissions(opts, addr, authorized, roundsDelay) - if err != nil { - return err - } - return f.client.ProcessTransaction(tx) +func (e *EthereumOffchainAggregatorV2) RequestNewRound() error { + _, err := e.client.Decode(e.contract.RequestNewRound(e.client.NewTXOpts())) + return err } -func (f *LegacyEthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), +func (e *EthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { + return e.contract.LatestAnswer(&bind.CallOpts{ + From: e.client.Addresses[0], Context: ctx, - } - addresses, err := f.fluxAggregator.GetOracles(opts) + }) +} + +func (e *EthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { + data, err := e.contract.LatestRoundData(&bind.CallOpts{ + From: e.client.Addresses[0], + Context: ctx, + }) if err != nil { return nil, err } - var oracleAddrs []string - for _, o := range addresses { - oracleAddrs = append(oracleAddrs, o.Hex()) - } - return oracleAddrs, nil + return &RoundData{ + RoundId: data.RoundId, + StartedAt: data.StartedAt, + UpdatedAt: data.UpdatedAt, + AnsweredInRound: data.AnsweredInRound, + Answer: data.Answer, + }, nil } -func (f *LegacyEthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), +func (e *EthereumOffchainAggregatorV2) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { + data, err := e.contract.GetRoundData(&bind.CallOpts{ + From: e.client.Addresses[0], Context: ctx, - } - rID, err := f.fluxAggregator.LatestRound(opts) + }, roundID) if err != nil { return nil, err } - return rID, nil + return &RoundData{ + RoundId: data.RoundId, + StartedAt: data.StartedAt, + UpdatedAt: data.UpdatedAt, + AnsweredInRound: data.AnsweredInRound, + Answer: data.Answer, + }, nil } -func (f *LegacyEthereumFluxAggregator) WithdrawPayment( - _ context.Context, - from common.Address, - to common.Address, - amount *big.Int) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err +func (e *EthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { + e.l.Info(). + Str("Transmitters", fmt.Sprintf("%v", transmitters)). + Str("Payees", fmt.Sprintf("%v", payees)). + Str("OCRv2 Address", e.Address()). + Msg("Setting OCRv2 Payees") + + var addTransmitters, addrPayees []common.Address + for _, t := range transmitters { + addTransmitters = append(addTransmitters, common.HexToAddress(t)) } - tx, err := f.fluxAggregator.WithdrawPayment(opts, from, to, amount) - if err != nil { - return err + for _, p := range payees { + addrPayees = append(addrPayees, common.HexToAddress(p)) } - return f.client.ProcessTransaction(tx) + + _, err := e.client.Decode(e.contract.SetPayees(e.client.NewTXOpts(), addTransmitters, addrPayees)) + return err } -func (f *LegacyEthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - balance, err := f.fluxAggregator.WithdrawablePayment(opts, addr) - if err != nil { - return nil, err - } - return balance, nil +func (e *EthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { + e.l.Info(). + Str("Address", e.Address()). + Interface("Signers", ocrConfig.Signers). + Interface("Transmitters", ocrConfig.Transmitters). + Uint8("F", ocrConfig.F). + Bytes("OnchainConfig", ocrConfig.OnchainConfig). + Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). + Bytes("OffchainConfig", ocrConfig.OffchainConfig). + Msg("Setting OCRv2 Config") + + _, err := e.client.Decode(e.contract.SetConfig( + e.client.NewTXOpts(), + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.OnchainConfig, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + )) + return err } -func (f *LegacyEthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } - lr, err := f.fluxAggregator.LatestRoundData(opts) - if err != nil { - return flux_aggregator_wrapper.LatestRoundData{}, err - } - return lr, nil +func (e *EthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { + return e.contract.ParseAnswerUpdated(log) } -// GetContractData retrieves basic data for the flux aggregator contract -func (f *LegacyEthereumFluxAggregator) GetContractData(ctx context.Context) (*FluxAggregatorData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctx, - } +// EthereumLinkToken represents a LinkToken address +type EthereumLinkToken struct { + client *seth.Client + instance *link_token_interface.LinkToken + address common.Address + l zerolog.Logger +} - allocated, err := f.fluxAggregator.AllocatedFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } +func (l *EthereumLinkToken) Decimals() uint { + return 18 +} - available, err := f.fluxAggregator.AvailableFunds(opts) +func DeployLinkTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumLinkToken, error) { + linkTokenAbi, err := link_token_interface.LinkTokenMetaData.GetAbi() if err != nil { - return &FluxAggregatorData{}, err + return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) } - - lr, err := f.fluxAggregator.LatestRoundData(opts) + linkDeploymentData, err := client.DeployContract(client.NewTXOpts(), "LinkToken", *linkTokenAbi, common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) if err != nil { - return &FluxAggregatorData{}, err + return &EthereumLinkToken{}, fmt.Errorf("LinkToken instance deployment have failed: %w", err) } - latestRound := RoundData(lr) - oracles, err := f.fluxAggregator.GetOracles(opts) + linkToken, err := link_token_interface.NewLinkToken(linkDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return &FluxAggregatorData{}, err + return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) } - return &FluxAggregatorData{ - AllocatedFunds: allocated, - AvailableFunds: available, - LatestRoundData: latestRound, - Oracles: oracles, + return &EthereumLinkToken{ + client: client, + instance: linkToken, + address: linkDeploymentData.Address, + l: l, }, nil } -// SetOracles allows the ability to add and/or remove oracles from the contract, and to set admins -func (f *LegacyEthereumFluxAggregator) SetOracles(o FluxAggregatorSetOraclesOptions) error { - opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := f.fluxAggregator.ChangeOracles(opts, o.RemoveList, o.AddList, o.AdminList, o.MinSubmissions, o.MaxSubmissions, o.RestartDelayRounds) +func LoadLinkTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumLinkToken, error) { + abi, err := link_token_interface.LinkTokenMetaData.GetAbi() if err != nil { - return err - } - return f.client.ProcessTransaction(tx) -} - -// Description returns the description of the flux aggregator contract -func (f *LegacyEthereumFluxAggregator) Description(ctxt context.Context) (string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(f.client.GetDefaultWallet().Address()), - Context: ctxt, + return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) } - return f.fluxAggregator.Description(opts) -} - -// FluxAggregatorRoundConfirmer is a header subscription that awaits for a certain flux round to be completed -type FluxAggregatorRoundConfirmer struct { - fluxInstance FluxAggregator - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - complete bool - l zerolog.Logger -} -// NewFluxAggregatorRoundConfirmer provides a new instance of a FluxAggregatorRoundConfirmer -func NewFluxAggregatorRoundConfirmer( - contract FluxAggregator, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *FluxAggregatorRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &FluxAggregatorRoundConfirmer{ - fluxInstance: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - l: logger, - } -} + client.ContractStore.AddABI("LinkToken", *abi) + client.ContractStore.AddBIN("LinkToken", common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) -// ReceiveHeader will query the latest FluxAggregator round and check to see whether the round has confirmed -func (f *FluxAggregatorRoundConfirmer) ReceiveHeader(header blockchain.NodeHeader) error { - if f.complete { - return nil - } - lr, err := f.fluxInstance.LatestRoundID(context.Background()) + linkToken, err := link_token_interface.NewLinkToken(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return err + return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) } - logFields := map[string]any{ - "Contract Address": f.fluxInstance.Address(), - "Current Round": lr.Int64(), - "Waiting for Round": f.roundID.Int64(), - "Header Number": header.Number.Uint64(), - } - if lr.Cmp(f.roundID) >= 0 { - f.l.Info().Fields(logFields).Msg("FluxAggregator round completed") - f.complete = true - f.doneChan <- struct{}{} - } else { - f.l.Debug().Fields(logFields).Msg("Waiting for FluxAggregator round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (f *FluxAggregatorRoundConfirmer) Wait() error { - defer func() { f.complete = true }() - for { - select { - case <-f.doneChan: - f.cancel() - return nil - case <-f.context.Done(): - return fmt.Errorf("timeout waiting for flux round to confirm: %d", f.roundID) - } - } -} - -func (f *FluxAggregatorRoundConfirmer) Complete() bool { - return f.complete -} -// LegacyEthereumLinkToken represents a LinkToken address -type LegacyEthereumLinkToken struct { - client blockchain.EVMClient - instance *link_token_interface.LinkToken - address common.Address - l zerolog.Logger + return &EthereumLinkToken{ + client: client, + instance: linkToken, + address: address, + l: l, + }, nil } // Fund the LINK Token contract with ETH to distribute the token -func (l *LegacyEthereumLinkToken) Fund(ethAmount *big.Float) error { - gasEstimates, err := l.client.EstimateGas(ethereum.CallMsg{ - To: &l.address, - }) - if err != nil { - return err - } - return l.client.Fund(l.address.Hex(), ethAmount, gasEstimates) +func (l *EthereumLinkToken) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds instead") } -func (l *LegacyEthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(l.client.GetDefaultWallet().Address()), +func (l *EthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { + return l.instance.BalanceOf(&bind.CallOpts{ + From: l.client.Addresses[0], Context: ctx, - } - balance, err := l.instance.BalanceOf(opts, common.HexToAddress(addr)) - if err != nil { - return nil, err - } - return balance, nil + }, common.HexToAddress(addr)) + } // Name returns the name of the link token -func (l *LegacyEthereumLinkToken) Name(ctxt context.Context) (string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(l.client.GetDefaultWallet().Address()), - Context: ctxt, - } - return l.instance.Name(opts) +func (l *EthereumLinkToken) Name(ctx context.Context) (string, error) { + return l.instance.Name(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: ctx, + }) } -func (l *LegacyEthereumLinkToken) Address() string { +func (l *EthereumLinkToken) Address() string { return l.address.Hex() } -func (l *LegacyEthereumLinkToken) Approve(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return err - } +func (l *EthereumLinkToken) Approve(to string, amount *big.Int) error { l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + Str("From", l.client.Addresses[0].Hex()). Str("To", to). Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). Msg("Approving LINK Transfer") - tx, err := l.instance.Approve(opts, common.HexToAddress(to), amount) - if err != nil { - return err - } - return l.client.ProcessTransaction(tx) + _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (l *LegacyEthereumLinkToken) Transfer(to string, amount *big.Int) error { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return err - } +func (l *EthereumLinkToken) Transfer(to string, amount *big.Int) error { l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + Str("From", l.client.Addresses[0].Hex()). Str("To", to). Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). Msg("Transferring LINK") - tx, err := l.instance.Transfer(opts, common.HexToAddress(to), amount) - if err != nil { - return err - } - return l.client.ProcessTransaction(tx) + _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (l *LegacyEthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { - opts, err := l.client.TransactionOpts(l.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := l.instance.TransferAndCall(opts, common.HexToAddress(to), amount, data) - if err != nil { - return nil, err - } +func (l *EthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { l.l.Info(). - Str("From", l.client.GetDefaultWallet().Address()). + Str("From", l.client.Addresses[0].Hex()). Str("To", to). Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Str("TxHash", tx.Hash().String()). Msg("Transferring and Calling LINK") - return tx, l.client.ProcessTransaction(tx) -} - -func (l *LegacyEthereumLinkToken) TransferAndCallFromKey(_ string, _ *big.Int, _ []byte, _ int) (*types.Transaction, error) { - panic("supported only with Seth") -} - -// LegacyEthereumOffchainAggregator represents the offchain aggregation contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOffchainAggregator instead -type LegacyEthereumOffchainAggregator struct { - client blockchain.EVMClient - ocr *offchainaggregator.OffchainAggregator - address *common.Address - l zerolog.Logger -} - -// SetPayees sets wallets for the contract to pay out to? -func (o *LegacyEthereumOffchainAggregator) SetPayees( - transmitters, payees []string, -) error { - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) + decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXOpts(), common.HexToAddress(to), amount, data)) if err != nil { - return err - } - var transmittersAddr, payeesAddr []common.Address - for _, tr := range transmitters { - transmittersAddr = append(transmittersAddr, common.HexToAddress(tr)) - } - for _, p := range payees { - payeesAddr = append(payeesAddr, common.HexToAddress(p)) + return nil, err } + return decodedTx.Transaction, nil +} - o.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCR Address", o.Address()). - Msg("Setting OCR Payees") - - tx, err := o.ocr.SetPayees(opts, transmittersAddr, payeesAddr) +func (l *EthereumLinkToken) TransferAndCallFromKey(to string, amount *big.Int, data []byte, keyNum int) (*types.Transaction, error) { + l.l.Info(). + Str("From", l.client.Addresses[keyNum].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Transferring and Calling LINK") + decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXKeyOpts(keyNum), common.HexToAddress(to), amount, data)) if err != nil { - return err + return nil, err } - return o.client.ProcessTransaction(tx) + return decodedTx.Transaction, nil } -// SetConfig sets the payees and the offchain reporting protocol configuration -func (o *LegacyEthereumOffchainAggregator) SetConfig( - chainlinkNodes []ChainlinkNodeWithKeysAndAddress, - ocrConfig OffChainAggregatorConfig, - transmitters []common.Address, -) error { - // Gather necessary addresses and keys from our chainlink nodes to properly configure the OCR contract - log.Info().Str("Contract Address", o.address.Hex()).Msg("Configuring OCR Contract") - for i, node := range chainlinkNodes { - ocrKeys, err := node.MustReadOCRKeys() - if err != nil { - return err - } - if len(ocrKeys.Data) == 0 { - return fmt.Errorf("no OCR keys found for node %v", node) - } - primaryOCRKey := ocrKeys.Data[0] - p2pKeys, err := node.MustReadP2PKeys() - if err != nil { - return err - } - primaryP2PKey := p2pKeys.Data[0] - - // Need to convert the key representations - var onChainSigningAddress [20]byte - var configPublicKey [32]byte - offchainSigningAddress, err := hex.DecodeString(primaryOCRKey.Attributes.OffChainPublicKey) - if err != nil { - return err - } - decodeConfigKey, err := hex.DecodeString(primaryOCRKey.Attributes.ConfigPublicKey) - if err != nil { - return err - } - - // https://stackoverflow.com/questions/8032170/how-to-assign-string-to-bytes-array - copy(onChainSigningAddress[:], common.HexToAddress(primaryOCRKey.Attributes.OnChainSigningAddress).Bytes()) - copy(configPublicKey[:], decodeConfigKey) - - oracleIdentity := ocrConfigHelper.OracleIdentity{ - TransmitAddress: transmitters[i], - OnChainSigningAddress: onChainSigningAddress, - PeerID: primaryP2PKey.Attributes.PeerID, - OffchainPublicKey: offchainSigningAddress, - } - oracleIdentityExtra := ocrConfigHelper.OracleIdentityExtra{ - OracleIdentity: oracleIdentity, - SharedSecretEncryptionPublicKey: ocrTypes.SharedSecretEncryptionPublicKey(configPublicKey), - } - - ocrConfig.OracleIdentities = append(ocrConfig.OracleIdentities, oracleIdentityExtra) +// DeployFluxAggregatorContract deploys the Flux Aggregator Contract on an EVM chain +func DeployFluxAggregatorContract( + seth *seth.Client, + linkAddr string, + fluxOptions FluxAggregatorOptions, +) (FluxAggregator, error) { + abi, err := flux_aggregator_wrapper.FluxAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumFluxAggregator{}, fmt.Errorf("failed to get FluxAggregator ABI: %w", err) } + seth.ContractStore.AddABI("FluxAggregator", *abi) + seth.ContractStore.AddBIN("FluxAggregator", common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin)) - signers, transmitters, threshold, encodedConfigVersion, encodedConfig, err := ocrConfigHelper.ContractSetConfigArgs( - ocrConfig.DeltaProgress, - ocrConfig.DeltaResend, - ocrConfig.DeltaRound, - ocrConfig.DeltaGrace, - ocrConfig.DeltaC, - ocrConfig.AlphaPPB, - ocrConfig.DeltaStage, - ocrConfig.RMax, - ocrConfig.S, - ocrConfig.OracleIdentities, - ocrConfig.F, + fluxDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "FluxAggregator", *abi, common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin), + common.HexToAddress(linkAddr), + fluxOptions.PaymentAmount, + fluxOptions.Timeout, + fluxOptions.Validator, + fluxOptions.MinSubValue, + fluxOptions.MaxSubValue, + fluxOptions.Decimals, + fluxOptions.Description, ) - if err != nil { - return err - } - // Set Config - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := o.ocr.SetConfig(opts, signers, transmitters, threshold, encodedConfigVersion, encodedConfig) if err != nil { - return err + return &EthereumFluxAggregator{}, fmt.Errorf("FluxAggregator instance deployment have failed: %w", err) } - return o.client.ProcessTransaction(tx) -} -// RequestNewRound requests the OCR contract to create a new round -func (o *LegacyEthereumOffchainAggregator) RequestNewRound() error { - opts, err := o.client.TransactionOpts(o.client.GetDefaultWallet()) + flux, err := flux_aggregator_wrapper.NewFluxAggregator(fluxDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return err - } - tx, err := o.ocr.RequestNewRound(opts) - if err != nil { - return err + return &EthereumFluxAggregator{}, fmt.Errorf("failed to instantiate FluxAggregator instance: %w", err) } - o.l.Info().Str("Contract Address", o.address.Hex()).Msg("New OCR round requested") - return o.client.ProcessTransaction(tx) + return &EthereumFluxAggregator{ + client: seth, + address: &fluxDeploymentData.Address, + fluxAggregator: flux, + }, nil } -// GetLatestAnswer returns the latest answer from the OCR contract -func (o *LegacyEthereumOffchainAggregator) GetLatestAnswer(ctxt context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), - Context: ctxt, - } - return o.ocr.LatestAnswer(opts) +// EthereumFluxAggregator represents the basic flux aggregation contract +type EthereumFluxAggregator struct { + client *seth.Client + fluxAggregator *flux_aggregator_wrapper.FluxAggregator + address *common.Address } -func (o *LegacyEthereumOffchainAggregator) Address() string { - return o.address.Hex() +func (f *EthereumFluxAggregator) Address() string { + return f.address.Hex() } -// GetLatestRound returns data from the latest round -func (o *LegacyEthereumOffchainAggregator) GetLatestRound(ctx context.Context) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), - Context: ctx, - } - - roundData, err := o.ocr.LatestRoundData(opts) - if err != nil { - return nil, err - } - - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, err +// Fund sends specified currencies to the contract +func (f *EthereumFluxAggregator) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } -func (o *LegacyEthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := o.ocr.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) - if err != nil { - return nil, err - } - return data.UpdatedAt, nil +func (f *EthereumFluxAggregator) UpdateAvailableFunds() error { + _, err := f.client.Decode(f.fluxAggregator.UpdateAvailableFunds(f.client.NewTXOpts())) + return err } -// GetRound retrieves an OCR round by the round ID -func (o *LegacyEthereumOffchainAggregator) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(o.client.GetDefaultWallet().Address()), +func (f *EthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { + return f.fluxAggregator.PaymentAmount(&bind.CallOpts{ + From: f.client.Addresses[0], Context: ctx, - } - roundData, err := o.ocr.GetRoundData(opts, roundID) - if err != nil { - return nil, err - } - - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, nil + }) } -// ParseEventAnswerUpdated parses the log for event AnswerUpdated -func (o *LegacyEthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { - return o.ocr.ParseAnswerUpdated(eventLog) +func (f *EthereumFluxAggregator) RequestNewRound(context.Context) error { + _, err := f.client.Decode(f.fluxAggregator.RequestNewRound(f.client.NewTXOpts())) + return err } -// RunlogRoundConfirmer is a header subscription that awaits for a certain Runlog round to be completed -type RunlogRoundConfirmer struct { - consumer APIConsumer - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - l zerolog.Logger +// WatchSubmissionReceived subscribes to any submissions on a flux feed +func (f *EthereumFluxAggregator) WatchSubmissionReceived(_ context.Context, _ chan<- *SubmissionEvent) error { + panic("do not use this method, instead use XXXX") } -// NewRunlogRoundConfirmer provides a new instance of a RunlogRoundConfirmer -func NewRunlogRoundConfirmer( - contract APIConsumer, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *RunlogRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &RunlogRoundConfirmer{ - consumer: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - l: logger, - } +func (f *EthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { + _, err := f.client.Decode(f.fluxAggregator.SetRequesterPermissions(f.client.NewTXOpts(), addr, authorized, roundsDelay)) + return err } -// ReceiveHeader will query the latest Runlog round and check to see whether the round has confirmed -func (o *RunlogRoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - currentRoundID, err := o.consumer.RoundID(context.Background()) +func (f *EthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { + addresses, err := f.fluxAggregator.GetOracles(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) if err != nil { - return err + return nil, err } - logFields := map[string]any{ - "Contract Address": o.consumer.Address(), - "Current Round": currentRoundID.Int64(), - "Waiting for Round": o.roundID.Int64(), - } - if currentRoundID.Cmp(o.roundID) >= 0 { - o.l.Info().Fields(logFields).Msg("Runlog round completed") - o.doneChan <- struct{}{} - } else { - o.l.Debug().Fields(logFields).Msg("Waiting for Runlog round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *RunlogRoundConfirmer) Wait() error { - for { - select { - case <-o.doneChan: - o.cancel() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for OCR round to confirm: %d", o.roundID) - } + var oracleAddrs []string + for _, o := range addresses { + oracleAddrs = append(oracleAddrs, o.Hex()) } + return oracleAddrs, nil +} + +func (f *EthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { + return f.fluxAggregator.LatestRound(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) +} + +func (f *EthereumFluxAggregator) WithdrawPayment( + _ context.Context, + from common.Address, + to common.Address, + amount *big.Int) error { + _, err := f.client.Decode(f.fluxAggregator.WithdrawPayment(f.client.NewTXOpts(), from, to, amount)) + return err } -// OffchainAggregatorRoundConfirmer is a header subscription that awaits for a certain OCR round to be completed -type OffchainAggregatorRoundConfirmer struct { - ocrInstance OffchainAggregator - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - blocksSinceAnswer uint - complete bool - l zerolog.Logger +func (f *EthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { + return f.fluxAggregator.WithdrawablePayment(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }, addr) } -// NewOffchainAggregatorRoundConfirmer provides a new instance of a OffchainAggregatorRoundConfirmer -func NewOffchainAggregatorRoundConfirmer( - contract OffchainAggregator, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *OffchainAggregatorRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &OffchainAggregatorRoundConfirmer{ - ocrInstance: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - complete: false, - l: logger, - } +func (f *EthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { + return f.fluxAggregator.LatestRoundData(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, + }) } -// ReceiveHeader will query the latest OffchainAggregator round and check to see whether the round has confirmed -func (o *OffchainAggregatorRoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - if channelClosed(o.doneChan) { - return nil +// GetContractData retrieves basic data for the flux aggregator contract +func (f *EthereumFluxAggregator) GetContractData(ctx context.Context) (*FluxAggregatorData, error) { + opts := &bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctx, } - lr, err := o.ocrInstance.GetLatestRound(context.Background()) + allocated, err := f.fluxAggregator.AllocatedFunds(opts) if err != nil { - return err - } - o.blocksSinceAnswer++ - currRound := lr.RoundId - logFields := map[string]any{ - "Contract Address": o.ocrInstance.Address(), - "Current Round": currRound.Int64(), - "Waiting for Round": o.roundID.Int64(), - } - if currRound.Cmp(o.roundID) >= 0 { - o.l.Info().Fields(logFields).Msg("OCR round completed") - o.doneChan <- struct{}{} - o.complete = true - } else { - o.l.Debug().Fields(logFields).Msg("Waiting on OCR Round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *OffchainAggregatorRoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - close(o.doneChan) - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for OCR round to confirm: %d", o.roundID) - } + return &FluxAggregatorData{}, err } -} - -func (o *OffchainAggregatorRoundConfirmer) Complete() bool { - return o.complete -} -// OffchainAggregatorRoundConfirmer is a header subscription that awaits for a certain OCR round to be completed -type OffchainAggregatorV2RoundConfirmer struct { - ocrInstance OffchainAggregatorV2 - roundID *big.Int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - blocksSinceAnswer uint - complete bool - l zerolog.Logger -} - -// NewOffchainAggregatorRoundConfirmer provides a new instance of a OffchainAggregatorRoundConfirmer -func NewOffchainAggregatorV2RoundConfirmer( - contract OffchainAggregatorV2, - roundID *big.Int, - timeout time.Duration, - logger zerolog.Logger, -) *OffchainAggregatorV2RoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &OffchainAggregatorV2RoundConfirmer{ - ocrInstance: contract, - roundID: roundID, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - complete: false, - l: logger, + available, err := f.fluxAggregator.AvailableFunds(opts) + if err != nil { + return &FluxAggregatorData{}, err } -} -// ReceiveHeader will query the latest OffchainAggregator round and check to see whether the round has confirmed -func (o *OffchainAggregatorV2RoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - if channelClosed(o.doneChan) { - return nil + lr, err := f.fluxAggregator.LatestRoundData(opts) + if err != nil { + return &FluxAggregatorData{}, err } + latestRound := RoundData(lr) - lr, err := o.ocrInstance.GetLatestRound(context.Background()) + oracles, err := f.fluxAggregator.GetOracles(opts) if err != nil { - return err - } - o.blocksSinceAnswer++ - currRound := lr.RoundId - logFields := map[string]any{ - "Contract Address": o.ocrInstance.Address(), - "Current Round": currRound.Int64(), - "Waiting for Round": o.roundID.Int64(), - } - if currRound.Cmp(o.roundID) >= 0 { - o.l.Info().Fields(logFields).Msg("OCR round completed") - o.doneChan <- struct{}{} - o.complete = true - } else { - o.l.Debug().Fields(logFields).Msg("Waiting on OCR Round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *OffchainAggregatorV2RoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - close(o.doneChan) - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for OCR round to confirm: %d", o.roundID) - } + return &FluxAggregatorData{}, err } -} -func (o *OffchainAggregatorV2RoundConfirmer) Complete() bool { - return o.complete + return &FluxAggregatorData{ + AllocatedFunds: allocated, + AvailableFunds: available, + LatestRoundData: latestRound, + Oracles: oracles, + }, nil } -// LegacyEthereumMockETHLINKFeed represents mocked ETH/LINK feed contract -type LegacyEthereumMockETHLINKFeed struct { - client blockchain.EVMClient - feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator - address *common.Address +// SetOracles allows the ability to add and/or remove oracles from the contract, and to set admins +func (f *EthereumFluxAggregator) SetOracles(o FluxAggregatorSetOraclesOptions) error { + _, err := f.client.Decode(f.fluxAggregator.ChangeOracles(f.client.NewTXOpts(), o.RemoveList, o.AddList, o.AdminList, o.MinSubmissions, o.MaxSubmissions, o.RestartDelayRounds)) + if err != nil { + return err + } + return err } -func (v *LegacyEthereumMockETHLINKFeed) Address() string { - return v.address.Hex() +// Description returns the description of the flux aggregator contract +func (f *EthereumFluxAggregator) Description(ctxt context.Context) (string, error) { + return f.fluxAggregator.Description(&bind.CallOpts{ + From: f.client.Addresses[0], + Context: ctxt, + }) } -func (v *LegacyEthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) +func DeployOracle(seth *seth.Client, linkAddr string) (Oracle, error) { + abi, err := oracle_wrapper.OracleMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumOracle{}, fmt.Errorf("failed to get Oracle ABI: %w", err) } - return data.Ans, nil -} + seth.ContractStore.AddABI("Oracle", *abi) + seth.ContractStore.AddBIN("Oracle", common.FromHex(oracle_wrapper.OracleMetaData.Bin)) + + oracleDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "Oracle", *abi, common.FromHex(oracle_wrapper.OracleMetaData.Bin), + common.HexToAddress(linkAddr), + ) -func (v *LegacyEthereumMockETHLINKFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: context.Background(), - }) if err != nil { - return nil, err + return &EthereumOracle{}, fmt.Errorf("Oracle instance deployment have failed: %w", err) } - return data.UpdatedAt, nil -} -// LegacyEthereumMockGASFeed represents mocked Gas feed contract -type LegacyEthereumMockGASFeed struct { - client blockchain.EVMClient - feed *mock_gas_aggregator_wrapper.MockGASAggregator - address *common.Address -} + oracle, err := oracle_wrapper.NewOracle(oracleDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumOracle{}, fmt.Errorf("Oracle to instantiate FluxAggregator instance: %w", err) + } -func (v *LegacyEthereumMockGASFeed) Address() string { - return v.address.Hex() + return &EthereumOracle{ + client: seth, + address: &oracleDeploymentData.Address, + oracle: oracle, + }, nil } -// EthereumFlags represents flags contract -type EthereumFlags struct { - client blockchain.EVMClient - flags *flags_wrapper.Flags +// EthereumOracle oracle for "directrequest" job tests +type EthereumOracle struct { address *common.Address + client *seth.Client + oracle *oracle_wrapper.Oracle } -func (e *EthereumFlags) Address() string { +func (e *EthereumOracle) Address() string { return e.address.Hex() } -// GetFlag returns boolean if a flag was set for particular address -func (e *EthereumFlags) GetFlag(ctx context.Context, addr string) (bool, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - flag, err := e.flags.GetFlag(opts, common.HexToAddress(addr)) - if err != nil { - return false, err - } - return flag, nil -} - -// LegacyEthereumOperatorFactory represents operator factory contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOperatorFactory instead -type LegacyEthereumOperatorFactory struct { - address *common.Address - client blockchain.EVMClient - operatorFactory *operator_factory.OperatorFactory +func (e *EthereumOracle) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } -func (e *LegacyEthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { - return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) +// SetFulfillmentPermission sets fulfillment permission for particular address +func (e *EthereumOracle) SetFulfillmentPermission(address string, allowed bool) error { + _, err := e.client.Decode(e.oracle.SetFulfillmentPermission(e.client.NewTXOpts(), common.HexToAddress(address), allowed)) + return err } -func (e *LegacyEthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { - return e.operatorFactory.ParseOperatorCreated(eventLog) -} +func DeployAPIConsumer(seth *seth.Client, linkAddr string) (APIConsumer, error) { + abi, err := test_api_consumer_wrapper.TestAPIConsumerMetaData.GetAbi() + if err != nil { + return &EthereumAPIConsumer{}, fmt.Errorf("failed to get TestAPIConsumer ABI: %w", err) + } + seth.ContractStore.AddABI("TestAPIConsumer", *abi) + seth.ContractStore.AddBIN("TestAPIConsumer", common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin)) -func (e *LegacyEthereumOperatorFactory) Address() string { - return e.address.Hex() -} + consumerDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "TestAPIConsumer", *abi, common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin), + common.HexToAddress(linkAddr), + ) -func (e *LegacyEthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) if err != nil { - return nil, err + return &EthereumAPIConsumer{}, fmt.Errorf("TestAPIConsumer instance deployment have failed: %w", err) } - tx, err := e.operatorFactory.DeployNewOperatorAndForwarder(opts) + + consumer, err := test_api_consumer_wrapper.NewTestAPIConsumer(consumerDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) if err != nil { - return nil, err + return &EthereumAPIConsumer{}, fmt.Errorf("failed to instantiate TestAPIConsumer instance: %w", err) } - return tx, nil -} - -// LegacyEthereumOperator represents operator contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOperator instead -type LegacyEthereumOperator struct { - address common.Address - client blockchain.EVMClient - operator *operator_wrapper.Operator - l zerolog.Logger -} -func (e *LegacyEthereumOperator) Address() string { - return e.address.Hex() + return &EthereumAPIConsumer{ + client: seth, + address: &consumerDeploymentData.Address, + consumer: consumer, + }, nil } -func (e *LegacyEthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - e.l.Info(). - Str("ForwardersAddresses", fmt.Sprint(forwarders)). - Str("EoaAddresses", fmt.Sprint(eoa)). - Msg("Accepting Authorized Receivers") - tx, err := e.operator.AcceptAuthorizedReceivers(opts, forwarders, eoa) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +// EthereumAPIConsumer API consumer for job type "directrequest" tests +type EthereumAPIConsumer struct { + address *common.Address + client *seth.Client + consumer *test_api_consumer_wrapper.TestAPIConsumer } -// LegacyEthereumAuthorizedForwarder represents authorized forwarder contract -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumAuthorizedForwarder instead -type LegacyEthereumAuthorizedForwarder struct { - address common.Address - client blockchain.EVMClient - authorizedForwarder *authorized_forwarder.AuthorizedForwarder +func (e *EthereumAPIConsumer) Address() string { + return e.address.Hex() } -// Owner return authorized forwarder owner address -func (e *LegacyEthereumAuthorizedForwarder) Owner(ctx context.Context) (string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +func (e *EthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { + return e.consumer.CurrentRoundID(&bind.CallOpts{ + From: e.client.Addresses[0], Context: ctx, - } - owner, err := e.authorizedForwarder.Owner(opts) + }) +} - return owner.Hex(), err +func (e *EthereumAPIConsumer) Fund(_ *big.Float) error { + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } -func (e *LegacyEthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +func (e *EthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { + return e.consumer.Data(&bind.CallOpts{ + From: e.client.Addresses[0], Context: ctx, - } - authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) - if err != nil { - return nil, err - } - var sendersAddrs []string - for _, o := range authorizedSenders { - sendersAddrs = append(sendersAddrs, o.Hex()) - } - return sendersAddrs, nil + }) } -func (e *LegacyEthereumAuthorizedForwarder) Address() string { - return e.address.Hex() +// CreateRequestTo creates request to an oracle for particular jobID with params +func (e *EthereumAPIConsumer) CreateRequestTo( + oracleAddr string, + jobID [32]byte, + payment *big.Int, + url string, + path string, + times *big.Int, +) error { + _, err := e.client.Decode(e.consumer.CreateRequestTo(e.client.NewTXOpts(), common.HexToAddress(oracleAddr), jobID, payment, url, path, times)) + return err } -// EthereumMockAggregatorProxy represents mock aggregator proxy contract -type EthereumMockAggregatorProxy struct { - address *common.Address - client blockchain.EVMClient - mockAggregatorProxy *mock_aggregator_proxy.MockAggregatorProxy +// EthereumMockETHLINKFeed represents mocked ETH/LINK feed contract +type EthereumMockETHLINKFeed struct { + client *seth.Client + feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator + address *common.Address } -func (e *EthereumMockAggregatorProxy) Address() string { - return e.address.Hex() +func (v *EthereumMockETHLINKFeed) Address() string { + return v.address.Hex() } -func (e *EthereumMockAggregatorProxy) UpdateAggregator(aggregator common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.mockAggregatorProxy.UpdateAggregator(opts, aggregator) +func (v *EthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { + data, err := v.feed.LatestRoundData(&bind.CallOpts{ + From: v.client.Addresses[0], + Context: context.Background(), + }) if err != nil { - return err + return nil, err } - return e.client.ProcessTransaction(tx) + return data.Ans, nil } -func (e *EthereumMockAggregatorProxy) Aggregator() (common.Address, error) { - addr, err := e.mockAggregatorProxy.Aggregator(&bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), +func (v *EthereumMockETHLINKFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { + data, err := v.feed.LatestRoundData(&bind.CallOpts{ + From: v.client.Addresses[0], Context: context.Background(), }) if err != nil { - return common.Address{}, err + return nil, err } - return addr, nil + return data.UpdatedAt, nil } -func channelClosed(ch <-chan struct{}) bool { - select { - case <-ch: - return true - default: +func DeployMockETHLINKFeed(client *seth.Client, answer *big.Int) (MockETHLINKFeed, error) { + abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) + } + data, err := client.DeployContract(client.NewTXOpts(), "MockETHLINKFeed", *abi, common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin), answer) + if err != nil { + return &EthereumMockETHLINKFeed{}, fmt.Errorf("MockETHLINKFeed instance deployment have failed: %w", err) } - return false -} - -// Deprecated: we are moving away from blockchain.EVMClient, use EthereumOffchainAggregatorV2 instead -type LegacyEthereumOffchainAggregatorV2 struct { - address *common.Address - client blockchain.EVMClient - contract *ocr2aggregator.OCR2Aggregator - l zerolog.Logger -} - -// OCRv2Config represents the config for the OCRv2 contract -type OCRv2Config struct { - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - TypedOnchainConfig21 i_keeper_registry_master_wrapper_2_1.IAutomationV21PlusCommonOnchainConfigLegacy - TypedOnchainConfig22 i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig - OffchainConfigVersion uint64 - OffchainConfig []byte -} + instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) + } -func (e *LegacyEthereumOffchainAggregatorV2) Address() string { - return e.address.Hex() + return &EthereumMockETHLINKFeed{ + address: &data.Address, + client: client, + feed: instance, + }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) RequestNewRound() error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func LoadMockETHLINKFeed(client *seth.Client, address common.Address) (MockETHLINKFeed, error) { + abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() if err != nil { - return err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) } - tx, err := e.contract.RequestNewRound(opts) + client.ContractStore.AddABI("MockETHLINKFeed", *abi) + client.ContractStore.AddBIN("MockETHLINKFeed", common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin)) + + instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return err + return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) } - return e.client.ProcessTransaction(tx) + + return &EthereumMockETHLINKFeed{ + address: &address, + client: client, + feed: instance, + }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - return e.contract.LatestAnswer(opts) +// EthereumMockGASFeed represents mocked Gas feed contract +type EthereumMockGASFeed struct { + client *seth.Client + feed *mock_gas_aggregator_wrapper.MockGASAggregator + address *common.Address } -func (e *LegacyEthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, +func (v *EthereumMockGASFeed) Address() string { + return v.address.Hex() +} + +func DeployMockGASFeed(client *seth.Client, answer *big.Int) (MockGasFeed, error) { + abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) } - data, err := e.contract.LatestRoundData(opts) + data, err := client.DeployContract(client.NewTXOpts(), "MockGasFeed", *abi, common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin), answer) if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("MockGasFeed instance deployment have failed: %w", err) } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, - }, nil -} -func (e *LegacyEthereumOffchainAggregatorV2) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - data, err := e.contract.GetRoundData(opts, roundID) + instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, + + return &EthereumMockGASFeed{ + address: &data.Address, + client: client, + feed: instance, }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func LoadMockGASFeed(client *seth.Client, address common.Address) (MockGasFeed, error) { + abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() if err != nil { - return err - } - e.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCRv2 Address", e.Address()). - Msg("Setting OCRv2 Payees") - - var addTransmitters, addrPayees []common.Address - for _, t := range transmitters { - addTransmitters = append(addTransmitters, common.HexToAddress(t)) - } - for _, p := range payees { - addrPayees = append(addrPayees, common.HexToAddress(p)) + return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) } + client.ContractStore.AddABI("MockGasFeed", *abi) + client.ContractStore.AddBIN("MockGasFeed", common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin)) - tx, err := e.contract.SetPayees(opts, addTransmitters, addrPayees) + instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return err + return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) } - return e.client.ProcessTransaction(tx) + + return &EthereumMockGASFeed{ + address: &address, + client: client, + feed: instance, + }, nil } -func (e *LegacyEthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployMultiCallContract(client *seth.Client) (common.Address, error) { + abi, err := abi.JSON(strings.NewReader(MultiCallABI)) if err != nil { - return err - } - e.l.Info(). - Str("Address", e.Address()). - Interface("Signers", ocrConfig.Signers). - Interface("Transmitters", ocrConfig.Transmitters). - Uint8("F", ocrConfig.F). - Bytes("OnchainConfig", ocrConfig.OnchainConfig). - Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). - Bytes("OffchainConfig", ocrConfig.OffchainConfig). - Msg("Setting OCRv2 Config") - tx, err := e.contract.SetConfig( - opts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) + return common.Address{}, err + } + + data, err := client.DeployContract(client.NewTXOpts(), "MultiCall", abi, common.FromHex(MultiCallBIN)) if err != nil { - return err + return common.Address{}, fmt.Errorf("MultiCall instance deployment have failed: %w", err) } - return e.client.ProcessTransaction(tx) + + return data.Address, nil } -func (e *LegacyEthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { - return e.contract.ParseAnswerUpdated(log) +func LoadFunctionsCoordinator(seth *seth.Client, addr string) (FunctionsCoordinator, error) { + abi, err := functions_coordinator.FunctionsCoordinatorMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to get FunctionsCoordinator ABI: %w", err) + } + seth.ContractStore.AddABI("FunctionsCoordinator", *abi) + seth.ContractStore.AddBIN("FunctionsCoordinator", common.FromHex(functions_coordinator.FunctionsCoordinatorMetaData.Bin)) + + instance, err := functions_coordinator.NewFunctionsCoordinator(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to instantiate FunctionsCoordinator instance: %w", err) + } + + return &EthereumFunctionsCoordinator{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + }, err } -// EthereumKeeperRegistryCheckUpkeepGasUsageWrapper represents a gas wrapper for keeper registry -type EthereumKeeperRegistryCheckUpkeepGasUsageWrapper struct { - address *common.Address - client blockchain.EVMClient - gasUsageWrapper *gas_wrapper.KeeperRegistryCheckUpkeepGasUsageWrapper +type EthereumFunctionsCoordinator struct { + address common.Address + client *seth.Client + instance *functions_coordinator.FunctionsCoordinator } -func (e *EthereumKeeperRegistryCheckUpkeepGasUsageWrapper) Address() string { +func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { + return e.instance.GetThresholdPublicKey(e.client.NewCallOpts()) +} + +func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { + return e.instance.GetDONPublicKey(e.client.NewCallOpts()) +} + +func (e *EthereumFunctionsCoordinator) Address() string { return e.address.Hex() } -/* Functions 1_0_0 */ +func LoadFunctionsRouter(l zerolog.Logger, seth *seth.Client, addr string) (FunctionsRouter, error) { + abi, err := functions_router.FunctionsRouterMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsRouter{}, fmt.Errorf("failed to get FunctionsRouter ABI: %w", err) + } + seth.ContractStore.AddABI("FunctionsRouter", *abi) + seth.ContractStore.AddBIN("FunctionsRouter", common.FromHex(functions_router.FunctionsRouterMetaData.Bin)) + + instance, err := functions_router.NewFunctionsRouter(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsRouter{}, fmt.Errorf("failed to instantiate FunctionsRouter instance: %w", err) + } + + return &EthereumFunctionsRouter{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + l: l, + }, err +} -type LegacyEthereumFunctionsRouter struct { +type EthereumFunctionsRouter struct { address common.Address - client blockchain.EVMClient + client *seth.Client instance *functions_router.FunctionsRouter l zerolog.Logger } -func (e *LegacyEthereumFunctionsRouter) Address() string { +func (e *EthereumFunctionsRouter) Address() string { return e.address.Hex() } -func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { + tx, err := e.client.Decode(e.instance.CreateSubscriptionWithConsumer(e.client.NewTXOpts(), common.HexToAddress(consumer))) if err != nil { return 0, err } - tx, err := e.instance.CreateSubscriptionWithConsumer(opts, common.HexToAddress(consumer)) - if err != nil { - return 0, err - } - if err := e.client.ProcessTransaction(tx); err != nil { - return 0, err - } - r, err := e.client.GetTxReceipt(tx.Hash()) - if err != nil { - return 0, err + + if tx.Receipt == nil { + return 0, errors.New("transaction did not err, but the receipt is nil") } - for _, l := range r.Logs { + for _, l := range tx.Receipt.Logs { e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() } topicsMap := map[string]interface{}{} @@ -2126,7 +1400,7 @@ func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer e.l.Info().Str("EventName", ev.Name).Send() } topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} - topicOneHash := []common.Hash{r.Logs[0].Topics[1:][0]} + topicOneHash := []common.Hash{tx.Receipt.Logs[0].Topics[1:][0]} if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { return 0, fmt.Errorf("failed to decode topic value, err: %w", err) } @@ -2137,63 +1411,61 @@ func (e *LegacyEthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer return topicsMap["subscriptionId"].(uint64), nil } -type LegacyEthereumFunctionsCoordinator struct { - address common.Address - client blockchain.EVMClient - instance *functions_coordinator.FunctionsCoordinator -} +func DeployFunctionsLoadTestClient(seth *seth.Client, router string) (FunctionsLoadTestClient, error) { + operatorAbi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) + } + data, err := seth.DeployContract(seth.NewTXOpts(), "FunctionsLoadTestClient", *operatorAbi, common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin), common.HexToAddress(router)) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("FunctionsLoadTestClient instance deployment have failed: %w", err) + } -func (e *LegacyEthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), + instance, err := functions_load_test_client.NewFunctionsLoadTestClient(data.Address, seth.Client) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) } - return e.instance.GetThresholdPublicKey(opts) + + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: data.Address, + }, nil } -func (e *LegacyEthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), +// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance +func LoadFunctionsLoadTestClient(seth *seth.Client, addr string) (FunctionsLoadTestClient, error) { + abi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) } - return e.instance.GetDONPublicKey(opts) -} + seth.ContractStore.AddABI("FunctionsLoadTestClient", *abi) + seth.ContractStore.AddBIN("FunctionsLoadTestClient", common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin)) -func (e *LegacyEthereumFunctionsCoordinator) Address() string { - return e.address.Hex() + instance, err := functions_load_test_client.NewFunctionsLoadTestClient(common.HexToAddress(addr), seth.Client) + if err != nil { + return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) + } + + return &EthereumFunctionsLoadTestClient{ + client: seth, + instance: instance, + address: common.HexToAddress(addr), + }, err } -type LegacyEthereumFunctionsLoadTestClient struct { +type EthereumFunctionsLoadTestClient struct { address common.Address - client blockchain.EVMClient + client *seth.Client instance *functions_load_test_client.FunctionsLoadTestClient } -func (e *LegacyEthereumFunctionsLoadTestClient) Address() string { +func (e *EthereumFunctionsLoadTestClient) Address() string { return e.address.Hex() } -type EthereumFunctionsLoadStats struct { - LastRequestID string - LastResponse string - LastError string - Total uint32 - Succeeded uint32 - Errored uint32 - Empty uint32 -} - -func Bytes32ToSlice(a [32]byte) (r []byte) { - r = append(r, a[:]...) - return -} - -func (e *LegacyEthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: context.Background(), - } - lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(opts) +func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { + lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(e.client.NewCallOpts()) if err != nil { return nil, err } @@ -2208,341 +1480,199 @@ func (e *LegacyEthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLo }, nil } -func (e *LegacyEthereumFunctionsLoadTestClient) ResetStats() error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.instance.ResetStats(opts) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (e *EthereumFunctionsLoadTestClient) ResetStats() error { + _, err := e.client.Decode(e.instance.ResetStats(e.client.NewTXOpts())) + return err } -func (e *LegacyEthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.instance.SendRequest(opts, times, source, encryptedSecretsReferences, args, subscriptionId, jobId) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { + _, err := e.client.Decode(e.instance.SendRequest(e.client.NewTXOpts(), times, source, encryptedSecretsReferences, args, subscriptionId, jobId)) + return err } -func (e *LegacyEthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := e.instance.SendRequestWithDONHostedSecrets(opts, times, source, slotID, slotVersion, args, subscriptionId, donID) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { + _, err := e.client.Decode(e.instance.SendRequestWithDONHostedSecrets(e.client.NewTXOpts(), times, source, slotID, slotVersion, args, subscriptionId, donID)) + return err } -type EthereumMercuryVerifier struct { +// EthereumWETHToken represents a WETH address +type EthereumWETHToken struct { + client *seth.Client + instance *weth9_wrapper.WETH9 address common.Address - client blockchain.EVMClient - instance *verifier.Verifier l zerolog.Logger } -func (e *EthereumMercuryVerifier) Address() common.Address { - return e.address -} - -func (e *EthereumMercuryVerifier) Verify(signedReport []byte, sender common.Address) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployWETHTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumWETHToken, error) { + wethTokenAbi, err := weth9_wrapper.WETH9MetaData.GetAbi() if err != nil { - return err + return &EthereumWETHToken{}, fmt.Errorf("failed to get WETH token ABI: %w", err) } - tx, err := e.instance.Verify(opts, signedReport, sender) + wethDeploymentData, err := client.DeployContract(client.NewTXOpts(), "WETHToken", *wethTokenAbi, common.FromHex(weth9_wrapper.WETH9MetaData.Bin)) if err != nil { - return err + return &EthereumWETHToken{}, fmt.Errorf("WETH token instance deployment failed: %w", err) } - return e.client.ProcessTransaction(tx) -} -func (e *EthereumMercuryVerifier) SetConfig(feedId [32]byte, signers []common.Address, offchainTransmitters [][32]byte, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte, recipientAddressesAndWeights []verifier.CommonAddressAndWeight) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.SetConfig(opts, feedId, signers, offchainTransmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, recipientAddressesAndWeights) - e.l.Info().Err(err).Str("contractAddress", e.address.Hex()).Hex("feedId", feedId[:]).Msg("Called EthereumMercuryVerifier.SetConfig()") + wethToken, err := weth9_wrapper.NewWETH9(wethDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumWETHToken{}, fmt.Errorf("failed to instantiate WETHToken instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) + + return &EthereumWETHToken{ + client: client, + instance: wethToken, + address: wethDeploymentData.Address, + l: l, + }, nil } -func (e *EthereumMercuryVerifier) LatestConfigDetails(ctx context.Context, feedId [32]byte) (verifier.LatestConfigDetails, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - d, err := e.instance.LatestConfigDetails(opts, feedId) - e.l.Info().Err(err).Str("contractAddress", e.address.Hex()).Hex("feedId", feedId[:]). - Interface("details", d). - Msg("Called EthereumMercuryVerifier.LatestConfigDetails()") +func LoadWETHTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumWETHToken, error) { + abi, err := weth9_wrapper.WETH9MetaData.GetAbi() if err != nil { - return verifier.LatestConfigDetails{}, err + return &EthereumWETHToken{}, fmt.Errorf("failed to get WETH token ABI: %w", err) } - return d, nil -} - -type EthereumMercuryVerifierProxy struct { - address common.Address - client blockchain.EVMClient - instance *verifier_proxy.VerifierProxy - l zerolog.Logger -} -func (e *EthereumMercuryVerifierProxy) Address() common.Address { - return e.address -} + client.ContractStore.AddABI("WETHToken", *abi) + client.ContractStore.AddBIN("WETHToken", common.FromHex(weth9_wrapper.WETH9MetaData.Bin)) -func (e *EthereumMercuryVerifierProxy) InitializeVerifier(verifierAddress common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.InitializeVerifier(opts, verifierAddress) - e.l.Info().Err(err).Str("contractAddress", e.address.Hex()).Str("verifierAddress", verifierAddress.Hex()). - Msg("Called EthereumMercuryVerifierProxy.InitializeVerifier()") + wethToken, err := weth9_wrapper.NewWETH9(address, wrappers.MustNewWrappedContractBackend(nil, client)) if err != nil { - return nil, err + return &EthereumWETHToken{}, fmt.Errorf("failed to instantiate WETHToken instance: %w", err) } - return tx, e.client.ProcessTransaction(tx) -} -func (e *EthereumMercuryVerifierProxy) Verify(signedReport []byte, parameterPayload []byte, value *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if value != nil { - opts.Value = value - } - if err != nil { - return nil, err - } - tx, err := e.instance.Verify(opts, signedReport, parameterPayload) - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) + return &EthereumWETHToken{ + client: client, + instance: wethToken, + address: address, + l: l, + }, nil } -func (e *EthereumMercuryVerifierProxy) VerifyBulk(signedReports [][]byte, parameterPayload []byte, value *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if value != nil { - opts.Value = value - } - if err != nil { - return nil, err - } - tx, err := e.instance.VerifyBulk(opts, signedReports, parameterPayload) - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +// Fund the WETH Token contract with ETH to distribute the token +func (l *EthereumWETHToken) Fund(_ *big.Float) error { + panic("do not use this function, use actions_seth.SendFunds instead") } -func (e *EthereumMercuryVerifierProxy) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.SetFeeManager(opts, feeManager) - e.l.Info().Err(err).Str("feeManager", feeManager.Hex()).Msg("Called MercuryVerifierProxy.SetFeeManager()") - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +func (l *EthereumWETHToken) Decimals() uint { + return 18 } -type EthereumMercuryFeeManager struct { - address common.Address - client blockchain.EVMClient - instance *fee_manager.FeeManager - l zerolog.Logger -} +func (l *EthereumWETHToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { + return l.instance.BalanceOf(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: ctx, + }, common.HexToAddress(addr)) -func (e *EthereumMercuryFeeManager) Address() common.Address { - return e.address } -func (e *EthereumMercuryFeeManager) UpdateSubscriberDiscount(subscriber common.Address, feedId [32]byte, token common.Address, discount uint64) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.UpdateSubscriberDiscount(opts, subscriber, feedId, token, discount) - e.l.Info().Err(err).Msg("Called EthereumMercuryFeeManager.UpdateSubscriberDiscount()") - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +// Name returns the name of the weth token +func (l *EthereumWETHToken) Name(ctx context.Context) (string, error) { + return l.instance.Name(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: ctx, + }) } -type EthereumMercuryRewardManager struct { - address common.Address - client blockchain.EVMClient - instance *reward_manager.RewardManager - l zerolog.Logger +func (l *EthereumWETHToken) Address() string { + return l.address.Hex() } -func (e *EthereumMercuryRewardManager) Address() common.Address { - return e.address +func (l *EthereumWETHToken) Approve(to string, amount *big.Int) error { + l.l.Info(). + Str("From", l.client.Addresses[0].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Approving WETH Transfer") + _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -func (e *EthereumMercuryRewardManager) SetFeeManager(feeManager common.Address) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.SetFeeManager(opts, feeManager) - e.l.Info().Err(err).Str("feeManager", feeManager.Hex()).Msg("Called EthereumMercuryRewardManager.SetFeeManager()") - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +func (l *EthereumWETHToken) Transfer(to string, amount *big.Int) error { + l.l.Info(). + Str("From", l.client.Addresses[0].Hex()). + Str("To", to). + Str("Amount", amount.String()). + Msg("Transferring WETH") + _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) + return err } -type EthereumWERC20Mock struct { - address common.Address - client blockchain.EVMClient - instance *werc20_mock.WERC20Mock - l zerolog.Logger +// EthereumMockETHUSDFeed represents mocked ETH/USD feed contract +// For the integration tests, we also use this ETH/USD feed for LINK/USD feed since they have the same structure +type EthereumMockETHUSDFeed struct { + client *seth.Client + feed *mock_ethusd_aggregator_wrapper.MockETHUSDAggregator + address *common.Address } -func (e *EthereumWERC20Mock) Address() common.Address { - return e.address +func (l *EthereumMockETHUSDFeed) Decimals() uint { + return 8 } -func (e *EthereumWERC20Mock) Approve(to string, amount *big.Int) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - e.l.Info(). - Str("From", e.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Msg("Approving LINK Transfer") - tx, err := e.instance.Approve(opts, common.HexToAddress(to), amount) - if err != nil { - return err - } - return e.client.ProcessTransaction(tx) +func (l *EthereumMockETHUSDFeed) Address() string { + return l.address.Hex() } -func (e *EthereumWERC20Mock) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(e.client.GetDefaultWallet().Address()), - Context: ctx, - } - balance, err := e.instance.BalanceOf(opts, common.HexToAddress(addr)) +func (l *EthereumMockETHUSDFeed) LatestRoundData() (*big.Int, error) { + data, err := l.feed.LatestRoundData(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: context.Background(), + }) if err != nil { return nil, err } - return balance, nil + return data.Ans, nil } -func (e *EthereumWERC20Mock) Transfer(to string, amount *big.Int) error { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return err - } - e.l.Info(). - Str("From", e.client.GetDefaultWallet().Address()). - Str("To", to). - Str("Amount", amount.String()). - Uint64("Nonce", opts.Nonce.Uint64()). - Msg("EthereumWERC20Mock.Transfer()") - tx, err := e.instance.Transfer(opts, common.HexToAddress(to), amount) +func (l *EthereumMockETHUSDFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { + data, err := l.feed.LatestRoundData(&bind.CallOpts{ + From: l.client.Addresses[0], + Context: context.Background(), + }) if err != nil { - return err + return nil, err } - return e.client.ProcessTransaction(tx) + return data.UpdatedAt, nil } -func (e *EthereumWERC20Mock) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func DeployMockETHUSDFeed(client *seth.Client, answer *big.Int) (MockETHUSDFeed, error) { + abi, err := mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.GetAbi() if err != nil { - return nil, err + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to get MockETHUSDFeed ABI: %w", err) } - e.l.Info(). - Str("account", account.Hex()). - Str("amount", amount.String()). - Msg("EthereumWERC20Mock.Mint()") - tx, err := e.instance.Mint(opts, account, amount) + data, err := client.DeployContract(client.NewTXOpts(), "MockETHUSDFeed", *abi, common.FromHex(mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.Bin), answer) if err != nil { - return tx, err - } - return tx, e.client.ProcessTransaction(tx) -} - -func ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkK8sClient) []ChainlinkNodeWithKeysAndAddress { - var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) - for i, node := range k8sNodes { - nodesAsInterface[i] = node - } - - return nodesAsInterface -} - -func ChainlinkClientToChainlinkNodeWithKeysAndAddress(k8sNodes []*client.ChainlinkClient) []ChainlinkNodeWithKeysAndAddress { - var nodesAsInterface = make([]ChainlinkNodeWithKeysAndAddress, len(k8sNodes)) - for i, node := range k8sNodes { - nodesAsInterface[i] = node + return &EthereumMockETHUSDFeed{}, fmt.Errorf("MockETHUSDFeed instance deployment have failed: %w", err) } - return nodesAsInterface -} - -func V2OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregatorV2) []OffChainAggregatorWithRounds { - var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) - for i, contract := range contracts { - contractsAsInterface[i] = contract + instance, err := mock_ethusd_aggregator_wrapper.NewMockETHUSDAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to instantiate MockETHUSDFeed instance: %w", err) } - return contractsAsInterface + return &EthereumMockETHUSDFeed{ + address: &data.Address, + client: client, + feed: instance, + }, nil } -func V1OffChainAgrregatorToOffChainAggregatorWithRounds(contracts []OffchainAggregator) []OffChainAggregatorWithRounds { - var contractsAsInterface = make([]OffChainAggregatorWithRounds, len(contracts)) - for i, contract := range contracts { - contractsAsInterface[i] = contract +func LoadMockETHUSDFeed(client *seth.Client, address common.Address) (MockETHUSDFeed, error) { + abi, err := mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.GetAbi() + if err != nil { + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to get MockETHUSDFeed ABI: %w", err) } + client.ContractStore.AddABI("MockETHUSDFeed", *abi) + client.ContractStore.AddBIN("MockETHUSDFeed", common.FromHex(mock_ethusd_aggregator_wrapper.MockETHUSDAggregatorMetaData.Bin)) - return contractsAsInterface -} - -func GetRegistryContractABI(version contractsethereum.KeeperRegistryVersion) (*abi.ABI, error) { - var ( - contractABI *abi.ABI - err error - ) - switch version { - case contractsethereum.RegistryVersion_1_0, contractsethereum.RegistryVersion_1_1: - contractABI, err = keeper_registry_wrapper1_1.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_1_2: - contractABI, err = keeper_registry_wrapper1_2.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_1_3: - contractABI, err = keeper_registry_wrapper1_3.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_2_0: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() - case contractsethereum.RegistryVersion_2_1: - contractABI, err = iregistry21.IKeeperRegistryMasterMetaData.GetAbi() - case contractsethereum.RegistryVersion_2_2: - contractABI, err = iregistry22.IAutomationRegistryMasterMetaData.GetAbi() - default: - contractABI, err = keeper_registry_wrapper2_0.KeeperRegistryMetaData.GetAbi() + instance, err := mock_ethusd_aggregator_wrapper.NewMockETHUSDAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumMockETHUSDFeed{}, fmt.Errorf("failed to instantiate MockETHUSDFeed instance: %w", err) } - return contractABI, err + return &EthereumMockETHUSDFeed{ + address: &address, + client: client, + feed: instance, + }, nil } diff --git a/integration-tests/contracts/etherem_contracts_atlas_seth.go b/integration-tests/contracts/ethereum_contracts_atlas.go similarity index 100% rename from integration-tests/contracts/etherem_contracts_atlas_seth.go rename to integration-tests/contracts/ethereum_contracts_atlas.go diff --git a/integration-tests/contracts/ethereum_contracts_automation_seth.go b/integration-tests/contracts/ethereum_contracts_automation.go similarity index 86% rename from integration-tests/contracts/ethereum_contracts_automation_seth.go rename to integration-tests/contracts/ethereum_contracts_automation.go index 5f5bc0eaf0..c2c7576e0f 100644 --- a/integration-tests/contracts/ethereum_contracts_automation_seth.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -16,6 +16,9 @@ import ( "github.com/rs/zerolog" "github.com/smartcontractkit/seth" + cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + registrylogicc23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -28,12 +31,20 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" automationForwarderLogic "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_forwarder_logic" registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" + registrar23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_3" registrylogica22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_2" registrylogicb22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_2" registry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_wrapper_2_2" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_module_base" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" iregistry22 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" + + registrylogica23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3" + registrylogicb23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3" + registry23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_wrapper_2_3" + iregistry23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_v21_plus_common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_chain_module" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" @@ -127,6 +138,7 @@ type EthereumKeeperRegistry struct { registry2_0 *keeper_registry_wrapper2_0.KeeperRegistry registry2_1 *i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMaster registry2_2 *i_automation_registry_master_wrapper_2_2.IAutomationRegistryMaster + registry2_3 *i_automation_registry_master_wrapper_2_3.IAutomationRegistryMaster23 chainModule *i_chain_module.IChainModule address *common.Address l zerolog.Logger @@ -139,7 +151,7 @@ func (v *EthereumKeeperRegistry) ReorgProtectionEnabled() bool { } func (v *EthereumKeeperRegistry) ChainModuleAddress() common.Address { - if v.version == ethereum.RegistryVersion_2_2 { + if v.version >= ethereum.RegistryVersion_2_2 { return v.chainModule.Address() } return common.Address{} @@ -150,7 +162,7 @@ func (v *EthereumKeeperRegistry) Address() string { } func (v *EthereumKeeperRegistry) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address { @@ -159,6 +171,9 @@ func (v *EthereumKeeperRegistry) RegistryOwnerAddress() common.Address { } switch v.version { + case ethereum.RegistryVersion_2_3: + ownerAddress, _ := v.registry2_3.Owner(callOpts) + return ownerAddress case ethereum.RegistryVersion_2_2: ownerAddress, _ := v.registry2_2.Owner(callOpts) return ownerAddress @@ -198,6 +213,17 @@ func (v *EthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error ocrConfig.OffchainConfigVersion, ocrConfig.OffchainConfig, )) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.SetConfigTypeSafe(txOpts, + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.TypedOnchainConfig23, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + ocrConfig.BillingTokens, + ocrConfig.BillingConfigs, + )) default: return fmt.Errorf("SetConfigTypeSafe is not supported in keeper registry version %d", v.version) } @@ -280,8 +306,8 @@ func (v *EthereumKeeperRegistry) SetConfig(config KeeperRegistrySettings, ocrCon ocrConfig.OffchainConfig, )) return err - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("registry version 2.1 and 2.2 must use setConfigTypeSafe function") + case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2, ethereum.RegistryVersion_2_3: + return fmt.Errorf("registry version 2.1 2.2 and 2.3 must use setConfigTypeSafe function") default: return fmt.Errorf("keeper registry version %d is not supported", v.version) } @@ -298,6 +324,9 @@ func (v *EthereumKeeperRegistry) SetUpkeepOffchainConfig(id *big.Int, offchainCo case ethereum.RegistryVersion_2_2: _, err := v.client.Decode(v.registry2_2.SetUpkeepOffchainConfig(v.client.NewTXOpts(), id, offchainConfig)) return err + case ethereum.RegistryVersion_2_3: + _, err := v.client.Decode(v.registry2_3.SetUpkeepOffchainConfig(v.client.NewTXOpts(), id, offchainConfig)) + return err default: return fmt.Errorf("SetUpkeepOffchainConfig is not supported by keeper registry version %d", v.version) } @@ -321,6 +350,8 @@ func (v *EthereumKeeperRegistry) Pause() error { _, err = v.client.Decode(v.registry2_1.Pause(txOpts)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.Pause(txOpts)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.Pause(txOpts)) default: return fmt.Errorf("keeper registry version %d is not supported", v.version) } @@ -405,6 +436,8 @@ func (v *EthereumKeeperRegistry) AddUpkeepFundsFromKey(id *big.Int, amount *big. _, err = v.client.Decode(v.registry2_1.AddFunds(opts, id, amount)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.AddFunds(opts, id, amount)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.AddFunds(opts, id, amount)) } return err @@ -501,6 +534,8 @@ func (v *EthereumKeeperRegistry) GetUpkeepInfo(ctx context.Context, id *big.Int) }, nil case ethereum.RegistryVersion_2_2: return v.getUpkeepInfo22(opts, id) + case ethereum.RegistryVersion_2_3: + return v.getUpkeepInfo23(opts, id) } return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) @@ -525,6 +560,25 @@ func (v *EthereumKeeperRegistry) getUpkeepInfo22(opts *bind.CallOpts, id *big.In }, nil } +func (v *EthereumKeeperRegistry) getUpkeepInfo23(opts *bind.CallOpts, id *big.Int) (*UpkeepInfo, error) { + uk, err := v.registry2_3.GetUpkeep(opts, id) + if err != nil { + return nil, err + } + return &UpkeepInfo{ + Target: uk.Target.Hex(), + ExecuteGas: uk.PerformGas, + CheckData: uk.CheckData, + Balance: uk.Balance, + Admin: uk.Admin.Hex(), + MaxValidBlocknumber: uk.MaxValidBlocknumber, + LastPerformBlockNumber: uk.LastPerformedBlockNumber, + AmountSpent: uk.AmountSpent, + Paused: uk.Paused, + OffchainConfig: uk.OffchainConfig, + }, nil +} + func (v *EthereumKeeperRegistry) GetKeeperInfo(ctx context.Context, keeperAddr string) (*KeeperInfo, error) { opts := &bind.CallOpts{ From: v.client.MustGetRootKeyAddress(), @@ -544,7 +598,7 @@ func (v *EthereumKeeperRegistry) GetKeeperInfo(ctx context.Context, keeperAddr s info, err = v.registry1_2.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) case ethereum.RegistryVersion_1_3: info, err = v.registry1_3.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_2_0, ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: + case ethereum.RegistryVersion_2_0, ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2, ethereum.RegistryVersion_2_3: // this is not used anywhere return nil, fmt.Errorf("not supported") } @@ -588,7 +642,7 @@ func (v *EthereumKeeperRegistry) SetKeepers(keepers []string, payees []string, o ocrConfig.OffchainConfigVersion, ocrConfig.OffchainConfig, )) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: + case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2, ethereum.RegistryVersion_2_3: return fmt.Errorf("not supported") } @@ -634,7 +688,7 @@ func (v *EthereumKeeperRegistry) RegisterUpkeep(target string, gasLimit uint32, checkData, nil, //offchain config )) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: + case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2, ethereum.RegistryVersion_2_3: return fmt.Errorf("not supported") } @@ -660,6 +714,8 @@ func (v *EthereumKeeperRegistry) CancelUpkeep(id *big.Int) error { tx, err = v.client.Decode(v.registry2_1.CancelUpkeep(opts, id)) case ethereum.RegistryVersion_2_2: tx, err = v.client.Decode(v.registry2_2.CancelUpkeep(opts, id)) + case ethereum.RegistryVersion_2_3: + tx, err = v.client.Decode(v.registry2_3.CancelUpkeep(opts, id)) } txHash := "none" @@ -692,6 +748,8 @@ func (v *EthereumKeeperRegistry) SetUpkeepGasLimit(id *big.Int, gas uint32) erro _, err = v.client.Decode(v.registry2_1.SetUpkeepGasLimit(opts, id, gas)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.SetUpkeepGasLimit(opts, id, gas)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.SetUpkeepGasLimit(opts, id, gas)) default: return fmt.Errorf("keeper registry version %d is not supported for SetUpkeepGasLimit", v.version) } @@ -729,7 +787,7 @@ func (v *EthereumKeeperRegistry) GetKeeperList(ctx context.Context) ([]string, e return []string{}, err } list = state.Transmitters - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: + case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2, ethereum.RegistryVersion_2_3: return nil, fmt.Errorf("not supported") } @@ -757,6 +815,8 @@ func (v *EthereumKeeperRegistry) UpdateCheckData(id *big.Int, newCheckData []byt _, err = v.client.Decode(v.registry2_1.SetUpkeepCheckData(opts, id, newCheckData)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.SetUpkeepCheckData(opts, id, newCheckData)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.SetUpkeepCheckData(opts, id, newCheckData)) default: return fmt.Errorf("UpdateCheckData is not supported by keeper registry version %d", v.version) } @@ -774,6 +834,8 @@ func (v *EthereumKeeperRegistry) SetUpkeepTriggerConfig(id *big.Int, triggerConf _, err = v.client.Decode(v.registry2_1.SetUpkeepTriggerConfig(opts, id, triggerConfig)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.SetUpkeepTriggerConfig(opts, id, triggerConfig)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.SetUpkeepTriggerConfig(opts, id, triggerConfig)) default: return fmt.Errorf("SetUpkeepTriggerConfig is not supported by keeper registry version %d", v.version) } @@ -791,6 +853,8 @@ func (v *EthereumKeeperRegistry) SetUpkeepPrivilegeConfig(id *big.Int, privilege _, err = v.client.Decode(v.registry2_1.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig)) default: return fmt.Errorf("SetUpkeepPrivilegeConfig is not supported by keeper registry version %d", v.version) } @@ -812,6 +876,8 @@ func (v *EthereumKeeperRegistry) PauseUpkeep(id *big.Int) error { _, err = v.client.Decode(v.registry2_1.PauseUpkeep(opts, id)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.PauseUpkeep(opts, id)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.PauseUpkeep(opts, id)) default: return fmt.Errorf("PauseUpkeep is not supported by keeper registry version %d", v.version) } @@ -833,6 +899,8 @@ func (v *EthereumKeeperRegistry) UnpauseUpkeep(id *big.Int) error { _, err = v.client.Decode(v.registry2_1.UnpauseUpkeep(opts, id)) case ethereum.RegistryVersion_2_2: _, err = v.client.Decode(v.registry2_2.UnpauseUpkeep(opts, id)) + case ethereum.RegistryVersion_2_3: + _, err = v.client.Decode(v.registry2_3.UnpauseUpkeep(opts, id)) default: return fmt.Errorf("UnpauseUpkeep is not supported by keeper registry version %d", v.version) } @@ -903,6 +971,16 @@ func (v *EthereumKeeperRegistry) ParseUpkeepPerformedLog(log *types.Log) (*Upkee Success: parsedLog.Success, From: utils.ZeroAddress, }, nil + case ethereum.RegistryVersion_2_3: + parsedLog, err := v.registry2_3.ParseUpkeepPerformed(*log) + if err != nil { + return nil, err + } + return &UpkeepPerformedLog{ + Id: parsedLog.Id, + Success: parsedLog.Success, + From: utils.ZeroAddress, + }, nil } return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) } @@ -935,6 +1013,14 @@ func (v *EthereumKeeperRegistry) ParseStaleUpkeepReportLog(log *types.Log) (*Sta return &StaleUpkeepReportLog{ Id: parsedLog.Id, }, nil + case ethereum.RegistryVersion_2_3: + parsedLog, err := v.registry2_3.ParseStaleUpkeepReport(*log) + if err != nil { + return nil, err + } + return &StaleUpkeepReportLog{ + Id: parsedLog.Id, + }, nil } return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) } @@ -978,6 +1064,12 @@ func (v *EthereumKeeperRegistry) ParseUpkeepIdFromRegisteredLog(log *types.Log) return nil, err } return parsedLog.Id, nil + case ethereum.RegistryVersion_2_3: + parsedLog, err := v.registry2_3.ParseUpkeepRegistered(*log) + if err != nil { + return nil, err + } + return parsedLog.Id, nil } return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) @@ -1015,6 +1107,8 @@ func DeployKeeperRegistry( return deployRegistry21(client, opts, mode) case eth_contracts.RegistryVersion_2_2: return deployRegistry22(client, opts) + case eth_contracts.RegistryVersion_2_3: + return deployRegistry23(client, opts) default: return nil, fmt.Errorf("keeper registry version %d is not supported", opts.RegistryVersion) } @@ -1339,6 +1433,109 @@ func deployRegistry22(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegi }, err } +func deployRegistry23(client *seth.Client, opts *KeeperRegistryOpts) (KeeperRegistry, error) { + var chainModuleAddr common.Address + var err error + chainId := client.ChainID + + if chainId == networks.ScrollMainnet.ChainID || chainId == networks.ScrollSepolia.ChainID { + chainModuleAddr, err = deployScrollModule(client) + } else if chainId == networks.ArbitrumMainnet.ChainID || chainId == networks.ArbitrumSepolia.ChainID { + chainModuleAddr, err = deployArbitrumModule(client) + } else if chainId == networks.OptimismMainnet.ChainID || chainId == networks.OptimismSepolia.ChainID { + chainModuleAddr, err = deployOptimismModule(client) + } else { + chainModuleAddr, err = deployBaseModule(client) + } + if err != nil { + return nil, err + } + + automationForwarderLogicAddr, err := deployAutomationForwarderLogicSeth(client) + if err != nil { + return nil, err + } + + var allowedReadOnlyAddress common.Address + if chainId == networks.PolygonZkEvmMainnet.ChainID || chainId == networks.PolygonZkEvmCardona.ChainID { + allowedReadOnlyAddress = common.HexToAddress("0x1111111111111111111111111111111111111111") + } else { + allowedReadOnlyAddress = common.HexToAddress("0x0000000000000000000000000000000000000000") + } + + logicCAbi, err := registrylogicc23.AutomationRegistryLogicCMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistryLogicC2_3 ABI: %w", err) + } + + logicCData, err := client.DeployContract(client.NewTXOpts(), "AutomationRegistryLogicC2_3", *logicCAbi, common.FromHex(registrylogicc23.AutomationRegistryLogicCMetaData.Bin), + common.HexToAddress(opts.LinkAddr), + common.HexToAddress(opts.LinkUSDFeedAddr), + common.HexToAddress(opts.NativeUSDFeedAddr), + common.HexToAddress(opts.GasFeedAddr), + automationForwarderLogicAddr, + allowedReadOnlyAddress, + uint8(0), // onchain payout mode + common.HexToAddress(opts.WrappedNativeAddr), + ) + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("AutomationRegistryLogicC2_3 instance deployment have failed: %w", err) + } + + logicBAbi, err := registrylogicb23.AutomationRegistryLogicBMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistryLogicB2_3 ABI: %w", err) + } + + logicBData, err := client.DeployContract(client.NewTXOpts(), "AutomationRegistryLogicB2_3", *logicBAbi, common.FromHex(registrylogicb23.AutomationRegistryLogicBMetaData.Bin), + logicCData.Address, + ) + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("AutomationRegistryLogicB2_3 instance deployment have failed: %w", err) + } + + logicAAbi, err := registrylogica23.AutomationRegistryLogicAMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistryLogicA2_3 ABI: %w", err) + } + logicAData, err := client.DeployContract(client.NewTXOpts(), "AutomationRegistryLogicA2_3", *logicAAbi, common.FromHex(registrylogica23.AutomationRegistryLogicAMetaData.Bin), + logicBData.Address, + ) + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("AutomationRegistryLogicA2_3 instance deployment have failed: %w", err) + } + + abi, err := registry23.AutomationRegistryMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistry2_3 ABI: %w", err) + } + + data, err := client.DeployContract(client.NewTXOpts(), "AutomationRegistry2_3", *abi, common.FromHex(registry23.AutomationRegistryMetaData.Bin), + logicAData.Address, + ) + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("AutomationRegistry2_3 instance deployment have failed: %w", err) + } + + instance, err := iregistry23.NewIAutomationRegistryMaster23(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate AutomationRegistry2_3 instance: %w", err) + } + + chainModule, err := i_chain_module.NewIChainModule( + chainModuleAddr, + wrappers.MustNewWrappedContractBackend(nil, client), + ) + + return &EthereumKeeperRegistry{ + client: client, + version: eth_contracts.RegistryVersion_2_3, + registry2_3: instance, + chainModule: chainModule, + address: &data.Address, + }, err +} + // LoadKeeperRegistry returns deployed on given address EthereumKeeperRegistry func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) { var keeper *EthereumKeeperRegistry @@ -1356,6 +1553,8 @@ func LoadKeeperRegistry(l zerolog.Logger, client *seth.Client, address common.Ad keeper, err = loadRegistry2_1(client, address) case eth_contracts.RegistryVersion_2_2: // why the contract name is not the same as the actual contract name? keeper, err = loadRegistry2_2(client, address) + case eth_contracts.RegistryVersion_2_3: + keeper, err = loadRegistry2_3(client, address) default: return nil, fmt.Errorf("keeper registry version %d is not supported", registryVersion) } @@ -1495,6 +1694,27 @@ func loadRegistry2_2(client *seth.Client, address common.Address) (*EthereumKeep }, nil } +func loadRegistry2_3(client *seth.Client, address common.Address) (*EthereumKeeperRegistry, error) { + abi, err := iregistry23.IAutomationRegistryMaster23MetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to get AutomationRegistry2_3 ABI: %w", err) + } + + client.ContractStore.AddABI("AutomationRegistry2_3", *abi) + client.ContractStore.AddBIN("AutomationRegistry2_3", common.FromHex(iregistry23.IAutomationRegistryMaster23MetaData.Bin)) + + instance, err := iregistry23.NewIAutomationRegistryMaster23(address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumKeeperRegistry{}, fmt.Errorf("failed to instantiate AutomationRegistry2_3 instance: %w", err) + } + + return &EthereumKeeperRegistry{ + address: &address, + client: client, + registry2_3: instance, + }, nil +} + func deployAutomationForwarderLogicSeth(client *seth.Client) (common.Address, error) { abi, err := automationForwarderLogic.AutomationForwarderLogicMetaData.GetAbi() if err != nil { @@ -1567,6 +1787,7 @@ type EthereumKeeperRegistrar struct { registrar *keeper_registrar_wrapper1_2.KeeperRegistrar registrar20 *keeper_registrar_wrapper2_0.KeeperRegistrar registrar21 *registrar21.AutomationRegistrar + registrar23 *registrar23.AutomationRegistrar address *common.Address } @@ -1575,11 +1796,11 @@ func (v *EthereumKeeperRegistrar) Address() string { } func (v *EthereumKeeperRegistrar) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } // EncodeRegisterRequest encodes register request to call it through link token TransferAndCall -func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool) ([]byte, error) { +func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool, linkTokenAddr string) ([]byte, error) { if v.registrar20 != nil { registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.ABI)) if err != nil { @@ -1667,6 +1888,76 @@ func (v *EthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byt common.HexToAddress(senderAddr), ) return req, err + } else if v.registrar23 != nil { + registrarABI = cltypes.MustGetABI(registrar23.AutomationRegistrarABI) + + if isLogTrigger { + var topic0InBytes [32]byte + // bytes representation of 0x0000000000000000000000000000000000000000000000000000000000000000 + bytes0 := [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, 0, + } + if isMercury { + // bytes representation of 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd + topic0InBytes = [32]byte{209, 255, 233, 228, 85, 129, 193, 29, 125, 159, 46, 213, 247, 82, 23, 205, 75, 233, 248, 183, 238, 230, 175, 15, 109, 3, 244, 109, 229, 57, 86, 205} + } else { + // bytes representation of 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d + topic0InBytes = [32]byte{ + 61, 83, 163, 149, 80, 224, 70, 136, + 6, 88, 39, 243, 187, 134, 88, 76, + 176, 7, 171, 158, 188, 167, 235, + 213, 40, 231, 48, 28, 156, 49, 235, 93, + } + } + + logTriggerConfigStruct := acutils.IAutomationV21PlusCommonLogTriggerConfig{ + ContractAddress: common.HexToAddress(upkeepAddr), + FilterSelector: 0, + Topic0: topic0InBytes, + Topic1: bytes0, + Topic2: bytes0, + Topic3: bytes0, + } + encodedLogTriggerConfig, err := compatibleUtils.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct) + if err != nil { + return nil, err + } + + params := registrar23.AutomationRegistrar23RegistrationParams{ + UpkeepContract: common.HexToAddress(upkeepAddr), + Amount: amount, + AdminAddress: common.HexToAddress(adminAddr), + GasLimit: gasLimit, + TriggerType: uint8(1), // trigger type + BillingToken: common.HexToAddress(linkTokenAddr), + Name: name, + EncryptedEmail: email, + CheckData: checkData, + TriggerConfig: encodedLogTriggerConfig, + OffchainConfig: []byte{}, + } + + req, err := registrarABI.Methods["registerUpkeep"].Inputs.Pack(¶ms) + return req, err + } + + params := registrar23.AutomationRegistrar23RegistrationParams{ + UpkeepContract: common.HexToAddress(upkeepAddr), + Amount: amount, + AdminAddress: common.HexToAddress(adminAddr), + GasLimit: gasLimit, + TriggerType: uint8(0), // trigger type + BillingToken: common.HexToAddress(linkTokenAddr), + Name: name, + EncryptedEmail: email, + CheckData: checkData, + TriggerConfig: []byte{}, + OffchainConfig: []byte{}, + } + + encodedRegistrationParamsStruct, err := registrarABI.Methods["registerUpkeep"].Inputs.Pack(¶ms) + + return encodedRegistrationParamsStruct, err } registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.ABI)) if err != nil { @@ -1750,6 +2041,48 @@ func DeployKeeperRegistrar(client *seth.Client, registryVersion eth_contracts.Ke registrar21: instance, address: &data.Address, }, nil + } else if registryVersion == eth_contracts.RegistryVersion_2_3 { + abi, err := registrar23.AutomationRegistrarMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to get KeeperRegistrar2_3 ABI: %w", err) + } + // set default TriggerType to 0(conditional), AutoApproveConfigType to 2(auto approve enabled), AutoApproveMaxAllowed to 1000 + triggerConfigs := []registrar23.AutomationRegistrar23InitialTriggerConfig{ + {TriggerType: 0, AutoApproveType: registrarSettings.AutoApproveConfigType, + AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, + {TriggerType: 1, AutoApproveType: registrarSettings.AutoApproveConfigType, + AutoApproveMaxAllowed: uint32(registrarSettings.AutoApproveMaxAllowed)}, + } + + billingTokens := []common.Address{ + common.HexToAddress(linkAddr), + } + minRegistrationFees := []*big.Int{ + big.NewInt(10), + } + + data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistrar2_3", *abi, common.FromHex(registrar23.AutomationRegistrarMetaData.Bin), + common.HexToAddress(linkAddr), + common.HexToAddress(registrarSettings.RegistryAddr), + triggerConfigs, + billingTokens, + minRegistrationFees, + common.HexToAddress(registrarSettings.WETHTokenAddr), + ) + if err != nil { + return &EthereumKeeperRegistrar{}, fmt.Errorf("KeeperRegistrar2_3 instance deployment have failed: %w", err) + } + + instance, err := registrar23.NewAutomationRegistrar(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumKeeperRegistrar{}, fmt.Errorf("failed to instantiate KeeperRegistrar2_3 instance: %w", err) + } + + return &EthereumKeeperRegistrar{ + client: client, + registrar23: instance, + address: &data.Address, + }, nil } // non OCR registrar @@ -2008,7 +2341,7 @@ func (v *EthereumUpkeepCounter) Address() string { } func (v *EthereumUpkeepCounter) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumUpkeepCounter) Counter(ctx context.Context) (*big.Int, error) { return v.consumer.Counter(&bind.CallOpts{ @@ -2065,7 +2398,7 @@ func (v *EthereumUpkeepPerformCounterRestrictive) Address() string { } func (v *EthereumUpkeepPerformCounterRestrictive) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumUpkeepPerformCounterRestrictive) Counter(ctx context.Context) (*big.Int, error) { return v.consumer.GetCountPerforms(&bind.CallOpts{ @@ -2159,7 +2492,7 @@ func (v *EthereumKeeperConsumerPerformance) Address() string { } func (v *EthereumKeeperConsumerPerformance) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumKeeperConsumerPerformance) CheckEligible(ctx context.Context) (bool, error) { @@ -2278,7 +2611,7 @@ func (v *EthereumAutomationConsumerBenchmark) Address() string { } func (v *EthereumAutomationConsumerBenchmark) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") + panic("do not use this function, use actions.SendFunds instead") } func (v *EthereumAutomationConsumerBenchmark) CheckEligible(ctx context.Context, id *big.Int, _range *big.Int, firstEligibleBuffer *big.Int) (bool, error) { diff --git a/integration-tests/contracts/ethereum_contracts_seth.go b/integration-tests/contracts/ethereum_contracts_seth.go deleted file mode 100644 index 803a0a3bce..0000000000 --- a/integration-tests/contracts/ethereum_contracts_seth.go +++ /dev/null @@ -1,1330 +0,0 @@ -package contracts - -import ( - "context" - "encoding/hex" - "errors" - "fmt" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" - ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" - - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_coordinator" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_load_test_client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/flux_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethlink_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_gas_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_factory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/operator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/oracle_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/test_api_consumer_wrapper" -) - -// EthereumOffchainAggregator represents the offchain aggregation contract -type EthereumOffchainAggregator struct { - client *seth.Client - ocr *offchainaggregator.OffchainAggregator - address *common.Address - l zerolog.Logger -} - -func LoadOffchainAggregator(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregator, error) { - abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregator", *abi) - seth.ContractStore.AddBIN("OffChainAggregator", common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin)) - - ocr, err := offchainaggregator.NewOffchainAggregator(contractAddress, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregator{ - client: seth, - ocr: ocr, - address: &contractAddress, - l: l, - }, nil -} - -func DeployOffchainAggregator(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregator, error) { - abi, err := offchainaggregator.OffchainAggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - - ocrDeploymentData, err := seth.DeployContract( - seth.NewTXOpts(), - "OffChainAggregator", - *abi, - common.FromHex(offchainaggregator.OffchainAggregatorMetaData.Bin), - offchainOptions.MaximumGasPrice, - offchainOptions.ReasonableGasPrice, - offchainOptions.MicroLinkPerEth, - offchainOptions.LinkGweiPerObservation, - offchainOptions.LinkGweiPerTransmission, - linkTokenAddress, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description) - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - - ocr, err := offchainaggregator.NewOffchainAggregator(ocrDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return EthereumOffchainAggregator{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregator{ - client: seth, - ocr: ocr, - address: &ocrDeploymentData.Address, - l: l, - }, nil -} - -// SetPayees sets wallets for the contract to pay out to? -func (o *EthereumOffchainAggregator) SetPayees( - transmitters, payees []string, -) error { - var transmittersAddr, payeesAddr []common.Address - for _, tr := range transmitters { - transmittersAddr = append(transmittersAddr, common.HexToAddress(tr)) - } - for _, p := range payees { - payeesAddr = append(payeesAddr, common.HexToAddress(p)) - } - - o.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCR Address", o.Address()). - Msg("Setting OCR Payees") - - _, err := o.client.Decode(o.ocr.SetPayees(o.client.NewTXOpts(), transmittersAddr, payeesAddr)) - return err -} - -// SetConfig sets the payees and the offchain reporting protocol configuration -func (o *EthereumOffchainAggregator) SetConfig( - chainlinkNodes []ChainlinkNodeWithKeysAndAddress, - ocrConfig OffChainAggregatorConfig, - transmitters []common.Address, -) error { - // Gather necessary addresses and keys from our chainlink nodes to properly configure the OCR contract - log.Info().Str("Contract Address", o.address.Hex()).Msg("Configuring OCR Contract") - for i, node := range chainlinkNodes { - ocrKeys, err := node.MustReadOCRKeys() - if err != nil { - return err - } - if len(ocrKeys.Data) == 0 { - return fmt.Errorf("no OCR keys found for node %v", node) - } - primaryOCRKey := ocrKeys.Data[0] - p2pKeys, err := node.MustReadP2PKeys() - if err != nil { - return err - } - primaryP2PKey := p2pKeys.Data[0] - - // Need to convert the key representations - var onChainSigningAddress [20]byte - var configPublicKey [32]byte - offchainSigningAddress, err := hex.DecodeString(primaryOCRKey.Attributes.OffChainPublicKey) - if err != nil { - return err - } - decodeConfigKey, err := hex.DecodeString(primaryOCRKey.Attributes.ConfigPublicKey) - if err != nil { - return err - } - - // https://stackoverflow.com/questions/8032170/how-to-assign-string-to-bytes-array - copy(onChainSigningAddress[:], common.HexToAddress(primaryOCRKey.Attributes.OnChainSigningAddress).Bytes()) - copy(configPublicKey[:], decodeConfigKey) - - oracleIdentity := ocrConfigHelper.OracleIdentity{ - TransmitAddress: transmitters[i], - OnChainSigningAddress: onChainSigningAddress, - PeerID: primaryP2PKey.Attributes.PeerID, - OffchainPublicKey: offchainSigningAddress, - } - oracleIdentityExtra := ocrConfigHelper.OracleIdentityExtra{ - OracleIdentity: oracleIdentity, - SharedSecretEncryptionPublicKey: ocrTypes.SharedSecretEncryptionPublicKey(configPublicKey), - } - - ocrConfig.OracleIdentities = append(ocrConfig.OracleIdentities, oracleIdentityExtra) - } - - signers, transmitters, threshold, encodedConfigVersion, encodedConfig, err := ocrConfigHelper.ContractSetConfigArgs( - ocrConfig.DeltaProgress, - ocrConfig.DeltaResend, - ocrConfig.DeltaRound, - ocrConfig.DeltaGrace, - ocrConfig.DeltaC, - ocrConfig.AlphaPPB, - ocrConfig.DeltaStage, - ocrConfig.RMax, - ocrConfig.S, - ocrConfig.OracleIdentities, - ocrConfig.F, - ) - if err != nil { - return err - } - - // fails with error setting OCR config for contract '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82': both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified - // but we only have gasPrice set... It also fails with the same error when we enable EIP-1559 - // fails when we wait for it to be minted, inside the wrapper there's no error when we call it, so it must be something inside smart contract - // that's reverting it and maybe the error message is completely off - _, err = o.client.Decode(o.ocr.SetConfig(o.client.NewTXOpts(), signers, transmitters, threshold, encodedConfigVersion, encodedConfig)) - return err -} - -// RequestNewRound requests the OCR contract to create a new round -func (o *EthereumOffchainAggregator) RequestNewRound() error { - o.l.Info().Str("Contract Address", o.address.Hex()).Msg("New OCR round requested") - _, err := o.client.Decode(o.ocr.RequestNewRound(o.client.NewTXOpts())) - return err -} - -// GetLatestAnswer returns the latest answer from the OCR contract -func (o *EthereumOffchainAggregator) GetLatestAnswer(ctx context.Context) (*big.Int, error) { - return o.ocr.LatestAnswer(&bind.CallOpts{ - From: o.client.Addresses[0], - Context: ctx, - }) -} - -func (o *EthereumOffchainAggregator) Address() string { - return o.address.Hex() -} - -// GetLatestRound returns data from the latest round -func (o *EthereumOffchainAggregator) GetLatestRound(ctx context.Context) (*RoundData, error) { - roundData, err := o.ocr.LatestRoundData(&bind.CallOpts{ - From: o.client.Addresses[0], - Context: ctx, - }) - if err != nil { - return nil, err - } - - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, err -} - -func (o *EthereumOffchainAggregator) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := o.ocr.LatestRoundData(o.client.NewCallOpts()) - if err != nil { - return nil, err - } - return data.UpdatedAt, nil -} - -// GetRound retrieves an OCR round by the round ID -func (o *EthereumOffchainAggregator) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - roundData, err := o.ocr.GetRoundData(&bind.CallOpts{ - From: o.client.Addresses[0], - Context: ctx, - }, roundID) - if err != nil { - return nil, err - } - - return &RoundData{ - RoundId: roundData.RoundId, - Answer: roundData.Answer, - AnsweredInRound: roundData.AnsweredInRound, - StartedAt: roundData.StartedAt, - UpdatedAt: roundData.UpdatedAt, - }, nil -} - -// ParseEventAnswerUpdated parses the log for event AnswerUpdated -func (o *EthereumOffchainAggregator) ParseEventAnswerUpdated(eventLog types.Log) (*offchainaggregator.OffchainAggregatorAnswerUpdated, error) { - return o.ocr.ParseAnswerUpdated(eventLog) -} - -// LegacyEthereumOperatorFactory represents operator factory contract -type EthereumOperatorFactory struct { - address *common.Address - client *seth.Client - operatorFactory *operator_factory.OperatorFactory -} - -func DeployEthereumOperatorFactory(seth *seth.Client, linkTokenAddress common.Address) (EthereumOperatorFactory, error) { - abi, err := operator_factory.OperatorFactoryMetaData.GetAbi() - if err != nil { - return EthereumOperatorFactory{}, fmt.Errorf("failed to get OperatorFactory ABI: %w", err) - } - operatorData, err := seth.DeployContract(seth.NewTXOpts(), "OperatorFactory", *abi, common.FromHex(operator_factory.OperatorFactoryMetaData.Bin), linkTokenAddress) - if err != nil { - return EthereumOperatorFactory{}, fmt.Errorf("OperatorFactory instance deployment have failed: %w", err) - } - - operatorFactory, err := operator_factory.NewOperatorFactory(operatorData.Address, seth.Client) - if err != nil { - return EthereumOperatorFactory{}, fmt.Errorf("failed to instantiate OperatorFactory instance: %w", err) - } - - return EthereumOperatorFactory{ - address: &operatorData.Address, - client: seth, - operatorFactory: operatorFactory, - }, nil -} - -func (e *EthereumOperatorFactory) ParseAuthorizedForwarderCreated(eventLog types.Log) (*operator_factory.OperatorFactoryAuthorizedForwarderCreated, error) { - return e.operatorFactory.ParseAuthorizedForwarderCreated(eventLog) -} - -func (e *EthereumOperatorFactory) ParseOperatorCreated(eventLog types.Log) (*operator_factory.OperatorFactoryOperatorCreated, error) { - return e.operatorFactory.ParseOperatorCreated(eventLog) -} - -func (e *EthereumOperatorFactory) Address() string { - return e.address.Hex() -} - -func (e *EthereumOperatorFactory) DeployNewOperatorAndForwarder() (*types.Transaction, error) { - return e.operatorFactory.DeployNewOperatorAndForwarder(e.client.NewTXOpts()) -} - -// EthereumOperator represents operator contract -type EthereumOperator struct { - address *common.Address - client *seth.Client - operator *operator_wrapper.Operator - l zerolog.Logger -} - -func LoadEthereumOperator(logger zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOperator, error) { - - abi, err := operator_wrapper.OperatorMetaData.GetAbi() - if err != nil { - return EthereumOperator{}, err - } - seth.ContractStore.AddABI("EthereumOperator", *abi) - seth.ContractStore.AddBIN("EthereumOperator", common.FromHex(operator_wrapper.OperatorMetaData.Bin)) - - operator, err := operator_wrapper.NewOperator(contractAddress, seth.Client) - if err != nil { - return EthereumOperator{}, err - } - - return EthereumOperator{ - address: &contractAddress, - client: seth, - operator: operator, - l: logger, - }, nil -} - -func (e *EthereumOperator) Address() string { - return e.address.Hex() -} - -func (e *EthereumOperator) AcceptAuthorizedReceivers(forwarders []common.Address, eoa []common.Address) error { - e.l.Info(). - Str("ForwardersAddresses", fmt.Sprint(forwarders)). - Str("EoaAddresses", fmt.Sprint(eoa)). - Msg("Accepting Authorized Receivers") - _, err := e.client.Decode(e.operator.AcceptAuthorizedReceivers(e.client.NewTXOpts(), forwarders, eoa)) - return err -} - -// EthereumAuthorizedForwarder represents authorized forwarder contract -type EthereumAuthorizedForwarder struct { - address *common.Address - client *seth.Client - authorizedForwarder *authorized_forwarder.AuthorizedForwarder -} - -func LoadEthereumAuthorizedForwarder(seth *seth.Client, contractAddress common.Address) (EthereumAuthorizedForwarder, error) { - abi, err := authorized_forwarder.AuthorizedForwarderMetaData.GetAbi() - if err != nil { - return EthereumAuthorizedForwarder{}, err - } - seth.ContractStore.AddABI("AuthorizedForwarder", *abi) - seth.ContractStore.AddBIN("AuthorizedForwarder", common.FromHex(authorized_forwarder.AuthorizedForwarderMetaData.Bin)) - - authorizedForwarder, err := authorized_forwarder.NewAuthorizedForwarder(contractAddress, seth.Client) - if err != nil { - return EthereumAuthorizedForwarder{}, fmt.Errorf("failed to instantiate AuthorizedForwarder instance: %w", err) - } - - return EthereumAuthorizedForwarder{ - address: &contractAddress, - client: seth, - authorizedForwarder: authorizedForwarder, - }, nil -} - -// Owner return authorized forwarder owner address -func (e *EthereumAuthorizedForwarder) Owner(_ context.Context) (string, error) { - owner, err := e.authorizedForwarder.Owner(e.client.NewCallOpts()) - - return owner.Hex(), err -} - -func (e *EthereumAuthorizedForwarder) GetAuthorizedSenders(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - } - authorizedSenders, err := e.authorizedForwarder.GetAuthorizedSenders(opts) - if err != nil { - return nil, err - } - var sendersAddrs []string - for _, o := range authorizedSenders { - sendersAddrs = append(sendersAddrs, o.Hex()) - } - return sendersAddrs, nil -} - -func (e *EthereumAuthorizedForwarder) Address() string { - return e.address.Hex() -} - -type EthereumOffchainAggregatorV2 struct { - address *common.Address - client *seth.Client - contract *ocr2aggregator.OCR2Aggregator - l zerolog.Logger -} - -func LoadOffChainAggregatorV2(l zerolog.Logger, seth *seth.Client, contractAddress common.Address) (EthereumOffchainAggregatorV2, error) { - oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) - seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) - - ocr2, err := ocr2aggregator.NewOCR2Aggregator(contractAddress, seth.Client) - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregatorV2{ - client: seth, - contract: ocr2, - address: &contractAddress, - l: l, - }, nil -} - -func DeployOffchainAggregatorV2(l zerolog.Logger, seth *seth.Client, linkTokenAddress common.Address, offchainOptions OffchainOptions) (EthereumOffchainAggregatorV2, error) { - oAbi, err := ocr2aggregator.OCR2AggregatorMetaData.GetAbi() - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to get OffChain Aggregator ABI: %w", err) - } - seth.ContractStore.AddABI("OffChainAggregatorV2", *oAbi) - seth.ContractStore.AddBIN("OffChainAggregatorV2", common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin)) - - ocrDeploymentData2, err := seth.DeployContract(seth.NewTXOpts(), "OffChainAggregatorV2", *oAbi, common.FromHex(ocr2aggregator.OCR2AggregatorMetaData.Bin), - linkTokenAddress, - offchainOptions.MinimumAnswer, - offchainOptions.MaximumAnswer, - offchainOptions.BillingAccessController, - offchainOptions.RequesterAccessController, - offchainOptions.Decimals, - offchainOptions.Description, - ) - - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("OCR instance deployment have failed: %w", err) - } - - ocr2, err := ocr2aggregator.NewOCR2Aggregator(ocrDeploymentData2.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return EthereumOffchainAggregatorV2{}, fmt.Errorf("failed to instantiate OCR instance: %w", err) - } - - return EthereumOffchainAggregatorV2{ - client: seth, - contract: ocr2, - address: &ocrDeploymentData2.Address, - l: l, - }, nil -} - -func (e *EthereumOffchainAggregatorV2) Address() string { - return e.address.Hex() -} - -func (e *EthereumOffchainAggregatorV2) RequestNewRound() error { - _, err := e.client.Decode(e.contract.RequestNewRound(e.client.NewTXOpts())) - return err -} - -func (e *EthereumOffchainAggregatorV2) GetLatestAnswer(ctx context.Context) (*big.Int, error) { - return e.contract.LatestAnswer(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) -} - -func (e *EthereumOffchainAggregatorV2) GetLatestRound(ctx context.Context) (*RoundData, error) { - data, err := e.contract.LatestRoundData(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) - if err != nil { - return nil, err - } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, - }, nil -} - -func (e *EthereumOffchainAggregatorV2) GetRound(ctx context.Context, roundID *big.Int) (*RoundData, error) { - data, err := e.contract.GetRoundData(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }, roundID) - if err != nil { - return nil, err - } - return &RoundData{ - RoundId: data.RoundId, - StartedAt: data.StartedAt, - UpdatedAt: data.UpdatedAt, - AnsweredInRound: data.AnsweredInRound, - Answer: data.Answer, - }, nil -} - -func (e *EthereumOffchainAggregatorV2) SetPayees(transmitters, payees []string) error { - e.l.Info(). - Str("Transmitters", fmt.Sprintf("%v", transmitters)). - Str("Payees", fmt.Sprintf("%v", payees)). - Str("OCRv2 Address", e.Address()). - Msg("Setting OCRv2 Payees") - - var addTransmitters, addrPayees []common.Address - for _, t := range transmitters { - addTransmitters = append(addTransmitters, common.HexToAddress(t)) - } - for _, p := range payees { - addrPayees = append(addrPayees, common.HexToAddress(p)) - } - - _, err := e.client.Decode(e.contract.SetPayees(e.client.NewTXOpts(), addTransmitters, addrPayees)) - return err -} - -func (e *EthereumOffchainAggregatorV2) SetConfig(ocrConfig *OCRv2Config) error { - e.l.Info(). - Str("Address", e.Address()). - Interface("Signers", ocrConfig.Signers). - Interface("Transmitters", ocrConfig.Transmitters). - Uint8("F", ocrConfig.F). - Bytes("OnchainConfig", ocrConfig.OnchainConfig). - Uint64("OffchainConfigVersion", ocrConfig.OffchainConfigVersion). - Bytes("OffchainConfig", ocrConfig.OffchainConfig). - Msg("Setting OCRv2 Config") - - _, err := e.client.Decode(e.contract.SetConfig( - e.client.NewTXOpts(), - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - )) - return err -} - -func (e *EthereumOffchainAggregatorV2) ParseEventAnswerUpdated(log types.Log) (*ocr2aggregator.OCR2AggregatorAnswerUpdated, error) { - return e.contract.ParseAnswerUpdated(log) -} - -// EthereumLinkToken represents a LinkToken address -type EthereumLinkToken struct { - client *seth.Client - instance *link_token_interface.LinkToken - address common.Address - l zerolog.Logger -} - -func DeployLinkTokenContract(l zerolog.Logger, client *seth.Client) (*EthereumLinkToken, error) { - linkTokenAbi, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) - } - linkDeploymentData, err := client.DeployContract(client.NewTXOpts(), "LinkToken", *linkTokenAbi, common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("LinkToken instance deployment have failed: %w", err) - } - - linkToken, err := link_token_interface.NewLinkToken(linkDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) - } - - return &EthereumLinkToken{ - client: client, - instance: linkToken, - address: linkDeploymentData.Address, - l: l, - }, nil -} - -func LoadLinkTokenContract(l zerolog.Logger, client *seth.Client, address common.Address) (*EthereumLinkToken, error) { - abi, err := link_token_interface.LinkTokenMetaData.GetAbi() - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to get LinkToken ABI: %w", err) - } - - client.ContractStore.AddABI("LinkToken", *abi) - client.ContractStore.AddBIN("LinkToken", common.FromHex(link_token_interface.LinkTokenMetaData.Bin)) - - linkToken, err := link_token_interface.NewLinkToken(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumLinkToken{}, fmt.Errorf("failed to instantiate LinkToken instance: %w", err) - } - - return &EthereumLinkToken{ - client: client, - instance: linkToken, - address: address, - l: l, - }, nil -} - -// Fund the LINK Token contract with ETH to distribute the token -func (l *EthereumLinkToken) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds instead") -} - -func (l *EthereumLinkToken) BalanceOf(ctx context.Context, addr string) (*big.Int, error) { - return l.instance.BalanceOf(&bind.CallOpts{ - From: l.client.Addresses[0], - Context: ctx, - }, common.HexToAddress(addr)) - -} - -// Name returns the name of the link token -func (l *EthereumLinkToken) Name(ctx context.Context) (string, error) { - return l.instance.Name(&bind.CallOpts{ - From: l.client.Addresses[0], - Context: ctx, - }) -} - -func (l *EthereumLinkToken) Address() string { - return l.address.Hex() -} - -func (l *EthereumLinkToken) Approve(to string, amount *big.Int) error { - l.l.Info(). - Str("From", l.client.Addresses[0].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Approving LINK Transfer") - _, err := l.client.Decode(l.instance.Approve(l.client.NewTXOpts(), common.HexToAddress(to), amount)) - return err -} - -func (l *EthereumLinkToken) Transfer(to string, amount *big.Int) error { - l.l.Info(). - Str("From", l.client.Addresses[0].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Transferring LINK") - _, err := l.client.Decode(l.instance.Transfer(l.client.NewTXOpts(), common.HexToAddress(to), amount)) - return err -} - -func (l *EthereumLinkToken) TransferAndCall(to string, amount *big.Int, data []byte) (*types.Transaction, error) { - l.l.Info(). - Str("From", l.client.Addresses[0].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Transferring and Calling LINK") - decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXOpts(), common.HexToAddress(to), amount, data)) - if err != nil { - return nil, err - } - return decodedTx.Transaction, nil -} - -func (l *EthereumLinkToken) TransferAndCallFromKey(to string, amount *big.Int, data []byte, keyNum int) (*types.Transaction, error) { - l.l.Info(). - Str("From", l.client.Addresses[keyNum].Hex()). - Str("To", to). - Str("Amount", amount.String()). - Msg("Transferring and Calling LINK") - decodedTx, err := l.client.Decode(l.instance.TransferAndCall(l.client.NewTXKeyOpts(keyNum), common.HexToAddress(to), amount, data)) - if err != nil { - return nil, err - } - return decodedTx.Transaction, nil -} - -// DeployFluxAggregatorContract deploys the Flux Aggregator Contract on an EVM chain -func DeployFluxAggregatorContract( - seth *seth.Client, - linkAddr string, - fluxOptions FluxAggregatorOptions, -) (FluxAggregator, error) { - abi, err := flux_aggregator_wrapper.FluxAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumFluxAggregator{}, fmt.Errorf("failed to get FluxAggregator ABI: %w", err) - } - seth.ContractStore.AddABI("FluxAggregator", *abi) - seth.ContractStore.AddBIN("FluxAggregator", common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin)) - - fluxDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "FluxAggregator", *abi, common.FromHex(flux_aggregator_wrapper.FluxAggregatorMetaData.Bin), - common.HexToAddress(linkAddr), - fluxOptions.PaymentAmount, - fluxOptions.Timeout, - fluxOptions.Validator, - fluxOptions.MinSubValue, - fluxOptions.MaxSubValue, - fluxOptions.Decimals, - fluxOptions.Description, - ) - - if err != nil { - return &EthereumFluxAggregator{}, fmt.Errorf("FluxAggregator instance deployment have failed: %w", err) - } - - flux, err := flux_aggregator_wrapper.NewFluxAggregator(fluxDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumFluxAggregator{}, fmt.Errorf("failed to instantiate FluxAggregator instance: %w", err) - } - - return &EthereumFluxAggregator{ - client: seth, - address: &fluxDeploymentData.Address, - fluxAggregator: flux, - }, nil -} - -// EthereumFluxAggregator represents the basic flux aggregation contract -type EthereumFluxAggregator struct { - client *seth.Client - fluxAggregator *flux_aggregator_wrapper.FluxAggregator - address *common.Address -} - -func (f *EthereumFluxAggregator) Address() string { - return f.address.Hex() -} - -// Fund sends specified currencies to the contract -func (f *EthereumFluxAggregator) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") -} - -func (f *EthereumFluxAggregator) UpdateAvailableFunds() error { - _, err := f.client.Decode(f.fluxAggregator.UpdateAvailableFunds(f.client.NewTXOpts())) - return err -} - -func (f *EthereumFluxAggregator) PaymentAmount(ctx context.Context) (*big.Int, error) { - return f.fluxAggregator.PaymentAmount(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) -} - -func (f *EthereumFluxAggregator) RequestNewRound(context.Context) error { - _, err := f.client.Decode(f.fluxAggregator.RequestNewRound(f.client.NewTXOpts())) - return err -} - -// WatchSubmissionReceived subscribes to any submissions on a flux feed -func (f *EthereumFluxAggregator) WatchSubmissionReceived(_ context.Context, _ chan<- *SubmissionEvent) error { - panic("do not use this method, instead use XXXX") -} - -func (f *EthereumFluxAggregator) SetRequesterPermissions(_ context.Context, addr common.Address, authorized bool, roundsDelay uint32) error { - _, err := f.client.Decode(f.fluxAggregator.SetRequesterPermissions(f.client.NewTXOpts(), addr, authorized, roundsDelay)) - return err -} - -func (f *EthereumFluxAggregator) GetOracles(ctx context.Context) ([]string, error) { - addresses, err := f.fluxAggregator.GetOracles(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) - if err != nil { - return nil, err - } - var oracleAddrs []string - for _, o := range addresses { - oracleAddrs = append(oracleAddrs, o.Hex()) - } - return oracleAddrs, nil -} - -func (f *EthereumFluxAggregator) LatestRoundID(ctx context.Context) (*big.Int, error) { - return f.fluxAggregator.LatestRound(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) -} - -func (f *EthereumFluxAggregator) WithdrawPayment( - _ context.Context, - from common.Address, - to common.Address, - amount *big.Int) error { - _, err := f.client.Decode(f.fluxAggregator.WithdrawPayment(f.client.NewTXOpts(), from, to, amount)) - return err -} - -func (f *EthereumFluxAggregator) WithdrawablePayment(ctx context.Context, addr common.Address) (*big.Int, error) { - return f.fluxAggregator.WithdrawablePayment(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }, addr) -} - -func (f *EthereumFluxAggregator) LatestRoundData(ctx context.Context) (flux_aggregator_wrapper.LatestRoundData, error) { - return f.fluxAggregator.LatestRoundData(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - }) -} - -// GetContractData retrieves basic data for the flux aggregator contract -func (f *EthereumFluxAggregator) GetContractData(ctx context.Context) (*FluxAggregatorData, error) { - opts := &bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctx, - } - - allocated, err := f.fluxAggregator.AllocatedFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - available, err := f.fluxAggregator.AvailableFunds(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - lr, err := f.fluxAggregator.LatestRoundData(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - latestRound := RoundData(lr) - - oracles, err := f.fluxAggregator.GetOracles(opts) - if err != nil { - return &FluxAggregatorData{}, err - } - - return &FluxAggregatorData{ - AllocatedFunds: allocated, - AvailableFunds: available, - LatestRoundData: latestRound, - Oracles: oracles, - }, nil -} - -// SetOracles allows the ability to add and/or remove oracles from the contract, and to set admins -func (f *EthereumFluxAggregator) SetOracles(o FluxAggregatorSetOraclesOptions) error { - _, err := f.client.Decode(f.fluxAggregator.ChangeOracles(f.client.NewTXOpts(), o.RemoveList, o.AddList, o.AdminList, o.MinSubmissions, o.MaxSubmissions, o.RestartDelayRounds)) - if err != nil { - return err - } - return err -} - -// Description returns the description of the flux aggregator contract -func (f *EthereumFluxAggregator) Description(ctxt context.Context) (string, error) { - return f.fluxAggregator.Description(&bind.CallOpts{ - From: f.client.Addresses[0], - Context: ctxt, - }) -} - -func DeployOracle(seth *seth.Client, linkAddr string) (Oracle, error) { - abi, err := oracle_wrapper.OracleMetaData.GetAbi() - if err != nil { - return &EthereumOracle{}, fmt.Errorf("failed to get Oracle ABI: %w", err) - } - seth.ContractStore.AddABI("Oracle", *abi) - seth.ContractStore.AddBIN("Oracle", common.FromHex(oracle_wrapper.OracleMetaData.Bin)) - - oracleDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "Oracle", *abi, common.FromHex(oracle_wrapper.OracleMetaData.Bin), - common.HexToAddress(linkAddr), - ) - - if err != nil { - return &EthereumOracle{}, fmt.Errorf("Oracle instance deployment have failed: %w", err) - } - - oracle, err := oracle_wrapper.NewOracle(oracleDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumOracle{}, fmt.Errorf("Oracle to instantiate FluxAggregator instance: %w", err) - } - - return &EthereumOracle{ - client: seth, - address: &oracleDeploymentData.Address, - oracle: oracle, - }, nil -} - -// EthereumOracle oracle for "directrequest" job tests -type EthereumOracle struct { - address *common.Address - client *seth.Client - oracle *oracle_wrapper.Oracle -} - -func (e *EthereumOracle) Address() string { - return e.address.Hex() -} - -func (e *EthereumOracle) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") -} - -// SetFulfillmentPermission sets fulfillment permission for particular address -func (e *EthereumOracle) SetFulfillmentPermission(address string, allowed bool) error { - _, err := e.client.Decode(e.oracle.SetFulfillmentPermission(e.client.NewTXOpts(), common.HexToAddress(address), allowed)) - return err -} - -func DeployAPIConsumer(seth *seth.Client, linkAddr string) (APIConsumer, error) { - abi, err := test_api_consumer_wrapper.TestAPIConsumerMetaData.GetAbi() - if err != nil { - return &EthereumAPIConsumer{}, fmt.Errorf("failed to get TestAPIConsumer ABI: %w", err) - } - seth.ContractStore.AddABI("TestAPIConsumer", *abi) - seth.ContractStore.AddBIN("TestAPIConsumer", common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin)) - - consumerDeploymentData, err := seth.DeployContract(seth.NewTXOpts(), "TestAPIConsumer", *abi, common.FromHex(test_api_consumer_wrapper.TestAPIConsumerMetaData.Bin), - common.HexToAddress(linkAddr), - ) - - if err != nil { - return &EthereumAPIConsumer{}, fmt.Errorf("TestAPIConsumer instance deployment have failed: %w", err) - } - - consumer, err := test_api_consumer_wrapper.NewTestAPIConsumer(consumerDeploymentData.Address, wrappers.MustNewWrappedContractBackend(nil, seth)) - if err != nil { - return &EthereumAPIConsumer{}, fmt.Errorf("failed to instantiate TestAPIConsumer instance: %w", err) - } - - return &EthereumAPIConsumer{ - client: seth, - address: &consumerDeploymentData.Address, - consumer: consumer, - }, nil -} - -// EthereumAPIConsumer API consumer for job type "directrequest" tests -type EthereumAPIConsumer struct { - address *common.Address - client *seth.Client - consumer *test_api_consumer_wrapper.TestAPIConsumer -} - -func (e *EthereumAPIConsumer) Address() string { - return e.address.Hex() -} - -func (e *EthereumAPIConsumer) RoundID(ctx context.Context) (*big.Int, error) { - return e.consumer.CurrentRoundID(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) -} - -func (e *EthereumAPIConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") -} - -func (e *EthereumAPIConsumer) Data(ctx context.Context) (*big.Int, error) { - return e.consumer.Data(&bind.CallOpts{ - From: e.client.Addresses[0], - Context: ctx, - }) -} - -// CreateRequestTo creates request to an oracle for particular jobID with params -func (e *EthereumAPIConsumer) CreateRequestTo( - oracleAddr string, - jobID [32]byte, - payment *big.Int, - url string, - path string, - times *big.Int, -) error { - _, err := e.client.Decode(e.consumer.CreateRequestTo(e.client.NewTXOpts(), common.HexToAddress(oracleAddr), jobID, payment, url, path, times)) - return err -} - -// EthereumMockETHLINKFeed represents mocked ETH/LINK feed contract -type EthereumMockETHLINKFeed struct { - client *seth.Client - feed *mock_ethlink_aggregator_wrapper.MockETHLINKAggregator - address *common.Address -} - -func (v *EthereumMockETHLINKFeed) Address() string { - return v.address.Hex() -} - -func (v *EthereumMockETHLINKFeed) LatestRoundData() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: v.client.Addresses[0], - Context: context.Background(), - }) - if err != nil { - return nil, err - } - return data.Ans, nil -} - -func (v *EthereumMockETHLINKFeed) LatestRoundDataUpdatedAt() (*big.Int, error) { - data, err := v.feed.LatestRoundData(&bind.CallOpts{ - From: v.client.Addresses[0], - Context: context.Background(), - }) - if err != nil { - return nil, err - } - return data.UpdatedAt, nil -} - -func DeployMockETHLINKFeed(client *seth.Client, answer *big.Int) (MockETHLINKFeed, error) { - abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "MockETHLINKFeed", *abi, common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin), answer) - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("MockETHLINKFeed instance deployment have failed: %w", err) - } - - instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) - } - - return &EthereumMockETHLINKFeed{ - address: &data.Address, - client: client, - feed: instance, - }, nil -} - -func LoadMockETHLINKFeed(client *seth.Client, address common.Address) (MockETHLINKFeed, error) { - abi, err := mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to get MockETHLINKFeed ABI: %w", err) - } - client.ContractStore.AddABI("MockETHLINKFeed", *abi) - client.ContractStore.AddBIN("MockETHLINKFeed", common.FromHex(mock_ethlink_aggregator_wrapper.MockETHLINKAggregatorMetaData.Bin)) - - instance, err := mock_ethlink_aggregator_wrapper.NewMockETHLINKAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockETHLINKFeed{}, fmt.Errorf("failed to instantiate MockETHLINKFeed instance: %w", err) - } - - return &EthereumMockETHLINKFeed{ - address: &address, - client: client, - feed: instance, - }, nil -} - -// EthereumMockGASFeed represents mocked Gas feed contract -type EthereumMockGASFeed struct { - client *seth.Client - feed *mock_gas_aggregator_wrapper.MockGASAggregator - address *common.Address -} - -func (v *EthereumMockGASFeed) Address() string { - return v.address.Hex() -} - -func DeployMockGASFeed(client *seth.Client, answer *big.Int) (MockGasFeed, error) { - abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXOpts(), "MockGasFeed", *abi, common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin), answer) - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("MockGasFeed instance deployment have failed: %w", err) - } - - instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) - } - - return &EthereumMockGASFeed{ - address: &data.Address, - client: client, - feed: instance, - }, nil -} - -func LoadMockGASFeed(client *seth.Client, address common.Address) (MockGasFeed, error) { - abi, err := mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.GetAbi() - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to get MockGasFeed ABI: %w", err) - } - client.ContractStore.AddABI("MockGasFeed", *abi) - client.ContractStore.AddBIN("MockGasFeed", common.FromHex(mock_gas_aggregator_wrapper.MockGASAggregatorMetaData.Bin)) - - instance, err := mock_gas_aggregator_wrapper.NewMockGASAggregator(address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &EthereumMockGASFeed{}, fmt.Errorf("failed to instantiate MockGasFeed instance: %w", err) - } - - return &EthereumMockGASFeed{ - address: &address, - client: client, - feed: instance, - }, nil -} - -func DeployMultiCallContract(client *seth.Client) (common.Address, error) { - abi, err := abi.JSON(strings.NewReader(MultiCallABI)) - if err != nil { - return common.Address{}, err - } - - data, err := client.DeployContract(client.NewTXOpts(), "MultiCall", abi, common.FromHex(MultiCallBIN)) - if err != nil { - return common.Address{}, fmt.Errorf("MultiCall instance deployment have failed: %w", err) - } - - return data.Address, nil -} - -func LoadFunctionsCoordinator(seth *seth.Client, addr string) (FunctionsCoordinator, error) { - abi, err := functions_coordinator.FunctionsCoordinatorMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to get FunctionsCoordinator ABI: %w", err) - } - seth.ContractStore.AddABI("FunctionsCoordinator", *abi) - seth.ContractStore.AddBIN("FunctionsCoordinator", common.FromHex(functions_coordinator.FunctionsCoordinatorMetaData.Bin)) - - instance, err := functions_coordinator.NewFunctionsCoordinator(common.HexToAddress(addr), seth.Client) - if err != nil { - return &EthereumFunctionsCoordinator{}, fmt.Errorf("failed to instantiate FunctionsCoordinator instance: %w", err) - } - - return &EthereumFunctionsCoordinator{ - client: seth, - instance: instance, - address: common.HexToAddress(addr), - }, err -} - -type EthereumFunctionsCoordinator struct { - address common.Address - client *seth.Client - instance *functions_coordinator.FunctionsCoordinator -} - -func (e *EthereumFunctionsCoordinator) GetThresholdPublicKey() ([]byte, error) { - return e.instance.GetThresholdPublicKey(e.client.NewCallOpts()) -} - -func (e *EthereumFunctionsCoordinator) GetDONPublicKey() ([]byte, error) { - return e.instance.GetDONPublicKey(e.client.NewCallOpts()) -} - -func (e *EthereumFunctionsCoordinator) Address() string { - return e.address.Hex() -} - -func LoadFunctionsRouter(l zerolog.Logger, seth *seth.Client, addr string) (FunctionsRouter, error) { - abi, err := functions_router.FunctionsRouterMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsRouter{}, fmt.Errorf("failed to get FunctionsRouter ABI: %w", err) - } - seth.ContractStore.AddABI("FunctionsRouter", *abi) - seth.ContractStore.AddBIN("FunctionsRouter", common.FromHex(functions_router.FunctionsRouterMetaData.Bin)) - - instance, err := functions_router.NewFunctionsRouter(common.HexToAddress(addr), seth.Client) - if err != nil { - return &EthereumFunctionsRouter{}, fmt.Errorf("failed to instantiate FunctionsRouter instance: %w", err) - } - - return &EthereumFunctionsRouter{ - client: seth, - instance: instance, - address: common.HexToAddress(addr), - l: l, - }, err -} - -type EthereumFunctionsRouter struct { - address common.Address - client *seth.Client - instance *functions_router.FunctionsRouter - l zerolog.Logger -} - -func (e *EthereumFunctionsRouter) Address() string { - return e.address.Hex() -} - -func (e *EthereumFunctionsRouter) CreateSubscriptionWithConsumer(consumer string) (uint64, error) { - tx, err := e.client.Decode(e.instance.CreateSubscriptionWithConsumer(e.client.NewTXOpts(), common.HexToAddress(consumer))) - if err != nil { - return 0, err - } - - if tx.Receipt == nil { - return 0, errors.New("transaction did not err, but the receipt is nil") - } - for _, l := range tx.Receipt.Logs { - e.l.Info().Interface("Log", common.Bytes2Hex(l.Data)).Send() - } - topicsMap := map[string]interface{}{} - - fabi, err := abi.JSON(strings.NewReader(functions_router.FunctionsRouterABI)) - if err != nil { - return 0, err - } - for _, ev := range fabi.Events { - e.l.Info().Str("EventName", ev.Name).Send() - } - topicOneInputs := abi.Arguments{fabi.Events["SubscriptionCreated"].Inputs[0]} - topicOneHash := []common.Hash{tx.Receipt.Logs[0].Topics[1:][0]} - if err := abi.ParseTopicsIntoMap(topicsMap, topicOneInputs, topicOneHash); err != nil { - return 0, fmt.Errorf("failed to decode topic value, err: %w", err) - } - e.l.Info().Interface("NewTopicsDecoded", topicsMap).Send() - if topicsMap["subscriptionId"] == 0 { - return 0, fmt.Errorf("failed to decode subscription ID after creation") - } - return topicsMap["subscriptionId"].(uint64), nil -} - -func DeployFunctionsLoadTestClient(seth *seth.Client, router string) (FunctionsLoadTestClient, error) { - operatorAbi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) - } - data, err := seth.DeployContract(seth.NewTXOpts(), "FunctionsLoadTestClient", *operatorAbi, common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin), common.HexToAddress(router)) - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("FunctionsLoadTestClient instance deployment have failed: %w", err) - } - - instance, err := functions_load_test_client.NewFunctionsLoadTestClient(data.Address, seth.Client) - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) - } - - return &EthereumFunctionsLoadTestClient{ - client: seth, - instance: instance, - address: data.Address, - }, nil -} - -// LoadFunctionsLoadTestClient returns deployed on given address FunctionsLoadTestClient contract instance -func LoadFunctionsLoadTestClient(seth *seth.Client, addr string) (FunctionsLoadTestClient, error) { - abi, err := functions_load_test_client.FunctionsLoadTestClientMetaData.GetAbi() - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to get FunctionsLoadTestClient ABI: %w", err) - } - seth.ContractStore.AddABI("FunctionsLoadTestClient", *abi) - seth.ContractStore.AddBIN("FunctionsLoadTestClient", common.FromHex(functions_load_test_client.FunctionsLoadTestClientMetaData.Bin)) - - instance, err := functions_load_test_client.NewFunctionsLoadTestClient(common.HexToAddress(addr), seth.Client) - if err != nil { - return &EthereumFunctionsLoadTestClient{}, fmt.Errorf("failed to instantiate FunctionsLoadTestClient instance: %w", err) - } - - return &EthereumFunctionsLoadTestClient{ - client: seth, - instance: instance, - address: common.HexToAddress(addr), - }, err -} - -type EthereumFunctionsLoadTestClient struct { - address common.Address - client *seth.Client - instance *functions_load_test_client.FunctionsLoadTestClient -} - -func (e *EthereumFunctionsLoadTestClient) Address() string { - return e.address.Hex() -} - -func (e *EthereumFunctionsLoadTestClient) GetStats() (*EthereumFunctionsLoadStats, error) { - lr, lbody, lerr, total, succeeded, errored, empty, err := e.instance.GetStats(e.client.NewCallOpts()) - if err != nil { - return nil, err - } - return &EthereumFunctionsLoadStats{ - LastRequestID: string(Bytes32ToSlice(lr)), - LastResponse: string(lbody), - LastError: string(lerr), - Total: total, - Succeeded: succeeded, - Errored: errored, - Empty: empty, - }, nil -} - -func (e *EthereumFunctionsLoadTestClient) ResetStats() error { - _, err := e.client.Decode(e.instance.ResetStats(e.client.NewTXOpts())) - return err -} - -func (e *EthereumFunctionsLoadTestClient) SendRequest(times uint32, source string, encryptedSecretsReferences []byte, args []string, subscriptionId uint64, jobId [32]byte) error { - _, err := e.client.Decode(e.instance.SendRequest(e.client.NewTXOpts(), times, source, encryptedSecretsReferences, args, subscriptionId, jobId)) - return err -} - -func (e *EthereumFunctionsLoadTestClient) SendRequestWithDONHostedSecrets(times uint32, source string, slotID uint8, slotVersion uint64, args []string, subscriptionId uint64, donID [32]byte) error { - _, err := e.client.Decode(e.instance.SendRequestWithDONHostedSecrets(e.client.NewTXOpts(), times, source, slotID, slotVersion, args, subscriptionId, donID)) - return err -} diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 31c3cb32dc..84543627d4 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -2,49 +2,20 @@ package contracts import ( "context" - "errors" - "fmt" "math/big" - "strconv" - "strings" - "time" - geth "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" goabi "github.com/umbracle/ethgo/abi" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ac "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_compatible_utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_consumer_benchmark" registrar21 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registrar_wrapper2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_chain_module" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_keeper_registry_master_wrapper_2_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_performance_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_consumer_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_triggered_streams_lookup_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/perform_data_checker_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/streams_lookup_upkeep_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_counter_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_perform_counter_restrictive_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/upkeep_transcoder" ) var compatibleUtils = cltypes.MustGetABI(ac.AutomationCompatibleUtilsABI) @@ -53,7 +24,7 @@ var registrarABI = cltypes.MustGetABI(registrar21.AutomationRegistrarABI) type KeeperRegistrar interface { Address() string - EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool) ([]byte, error) + EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool, linkTokenAddr string) ([]byte, error) Fund(ethAmount *big.Float) error } @@ -153,13 +124,16 @@ type StaleUpkeepReportLog struct { // KeeperRegistryOpts opts to deploy keeper registry version type KeeperRegistryOpts struct { - RegistryVersion ethereum.KeeperRegistryVersion - LinkAddr string - ETHFeedAddr string - GasFeedAddr string - TranscoderAddr string - RegistrarAddr string - Settings KeeperRegistrySettings + RegistryVersion ethereum.KeeperRegistryVersion + LinkAddr string + ETHFeedAddr string + GasFeedAddr string + TranscoderAddr string + RegistrarAddr string + Settings KeeperRegistrySettings + LinkUSDFeedAddr string + NativeUSDFeedAddr string + WrappedNativeAddr string } // KeeperRegistrySettings represents the settings to fine tune keeper registry @@ -180,74 +154,45 @@ type KeeperRegistrySettings struct { RegistryVersion ethereum.KeeperRegistryVersion } -// KeeperRegistrarSettings represents settings for registrar contract -type KeeperRegistrarSettings struct { - AutoApproveConfigType uint8 - AutoApproveMaxAllowed uint16 - RegistryAddr string - MinLinkJuels *big.Int -} - -// KeeperInfo keeper status and balance info -type KeeperInfo struct { - Payee string - Active bool - Balance *big.Int -} - -// UpkeepInfo keeper target info -type UpkeepInfo struct { - Target string - ExecuteGas uint32 - CheckData []byte - Balance *big.Int - LastKeeper string - Admin string - MaxValidBlocknumber uint64 - LastPerformBlockNumber uint32 - AmountSpent *big.Int - Paused bool - OffchainConfig []byte -} - -// LegacyEthereumKeeperRegistry represents keeper registry contract -type LegacyEthereumKeeperRegistry struct { - client blockchain.EVMClient - version ethereum.KeeperRegistryVersion - registry1_1 *keeper_registry_wrapper1_1.KeeperRegistry - registry1_2 *keeper_registry_wrapper1_2.KeeperRegistry - registry1_3 *keeper_registry_wrapper1_3.KeeperRegistry - registry2_0 *keeper_registry_wrapper2_0.KeeperRegistry - registry2_1 *i_keeper_registry_master_wrapper_2_1.IKeeperRegistryMaster - registry2_2 *i_automation_registry_master_wrapper_2_2.IAutomationRegistryMaster - chainModule *i_chain_module.IChainModule - address *common.Address - l zerolog.Logger -} - -func (v *LegacyEthereumKeeperRegistry) ReorgProtectionEnabled() bool { - chainId := v.client.GetChainID().Uint64() - // reorg protection is disabled in polygon zkEVM and Scroll bc currently there is no way to get the block hash onchain - return v.version != ethereum.RegistryVersion_2_2 || (chainId != 1101 && chainId != 1442 && chainId != 2442 && chainId != 534352 && chainId != 534351) -} - -func (v *LegacyEthereumKeeperRegistry) ChainModuleAddress() common.Address { - if v.version == ethereum.RegistryVersion_2_2 { - return v.chainModule.Address() +func (rcs *KeeperRegistrySettings) Create23OnchainConfig(registrar string, registryOwnerAddress, chainModuleAddress common.Address, reorgProtectionEnabled bool) i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig { + return i_automation_registry_master_wrapper_2_3.AutomationRegistryBase23OnchainConfig{ + CheckGasLimit: rcs.CheckGasLimit, + StalenessSeconds: rcs.StalenessSeconds, + GasCeilingMultiplier: rcs.GasCeilingMultiplier, + MaxPerformGas: rcs.MaxPerformGas, + MaxCheckDataSize: rcs.MaxCheckDataSize, + MaxPerformDataSize: rcs.MaxPerformDataSize, + MaxRevertDataSize: rcs.MaxRevertDataSize, + FallbackGasPrice: rcs.FallbackGasPrice, + FallbackLinkPrice: rcs.FallbackLinkPrice, + Transcoder: common.Address{}, + Registrars: []common.Address{common.HexToAddress(registrar)}, + UpkeepPrivilegeManager: registryOwnerAddress, + ChainModule: chainModuleAddress, + ReorgProtectionEnabled: reorgProtectionEnabled, + FinanceAdmin: registryOwnerAddress, + FallbackNativePrice: big.NewInt(1), } - return common.Address{} -} - -func (v *LegacyEthereumKeeperRegistry) Address() string { - return v.address.Hex() } -func (v *LegacyEthereumKeeperRegistry) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) +func (rcs *KeeperRegistrySettings) Encode20OnchainConfig(registrar string) []byte { + configType := goabi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)") + onchainConfig, _ := goabi.Encode(map[string]interface{}{ + "paymentPremiumPPB": rcs.PaymentPremiumPPB, + "flatFeeMicroLink": rcs.FlatFeeMicroLINK, + "checkGasLimit": rcs.CheckGasLimit, + "stalenessSeconds": rcs.StalenessSeconds, + "gasCeilingMultiplier": rcs.GasCeilingMultiplier, + "minUpkeepSpend": rcs.MinUpkeepSpend, + "maxPerformGas": rcs.MaxPerformGas, + "maxCheckDataSize": rcs.MaxCheckDataSize, + "maxPerformDataSize": rcs.MaxPerformDataSize, + "fallbackGasPrice": rcs.FallbackGasPrice, + "fallbackLinkPrice": rcs.FallbackLinkPrice, + "transcoder": common.Address{}, + "registrar": registrar, + }, configType) + return onchainConfig } func (rcs *KeeperRegistrySettings) Create22OnchainConfig(registrar string, registryOwnerAddress, chainModuleAddress common.Address, reorgProtectionEnabled bool) i_automation_registry_master_wrapper_2_2.AutomationRegistryBase22OnchainConfig { @@ -292,2077 +237,33 @@ func (rcs *KeeperRegistrySettings) Create21OnchainConfig(registrar string, regis } } -func (rcs *KeeperRegistrySettings) Encode20OnchainConfig(registrar string) []byte { - configType := goabi.MustNewType("tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,address registrar)") - onchainConfig, _ := goabi.Encode(map[string]interface{}{ - "paymentPremiumPPB": rcs.PaymentPremiumPPB, - "flatFeeMicroLink": rcs.FlatFeeMicroLINK, - "checkGasLimit": rcs.CheckGasLimit, - "stalenessSeconds": rcs.StalenessSeconds, - "gasCeilingMultiplier": rcs.GasCeilingMultiplier, - "minUpkeepSpend": rcs.MinUpkeepSpend, - "maxPerformGas": rcs.MaxPerformGas, - "maxCheckDataSize": rcs.MaxCheckDataSize, - "maxPerformDataSize": rcs.MaxPerformDataSize, - "fallbackGasPrice": rcs.FallbackGasPrice, - "fallbackLinkPrice": rcs.FallbackLinkPrice, - "transcoder": common.Address{}, - "registrar": registrar, - }, configType) - return onchainConfig -} - -func (v *LegacyEthereumKeeperRegistry) RegistryOwnerAddress() common.Address { - callOpts := &bind.CallOpts{ - Pending: false, - } - - //nolint: exhaustive - switch v.version { - case ethereum.RegistryVersion_2_2: - ownerAddress, _ := v.registry2_2.Owner(callOpts) - return ownerAddress - case ethereum.RegistryVersion_2_1: - ownerAddress, _ := v.registry2_1.Owner(callOpts) - return ownerAddress - case ethereum.RegistryVersion_2_0: - ownerAddress, _ := v.registry2_0.Owner(callOpts) - return ownerAddress - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1, ethereum.RegistryVersion_1_2, ethereum.RegistryVersion_1_3: - return common.HexToAddress(v.client.GetDefaultWallet().Address()) - } - - return common.HexToAddress(v.client.GetDefaultWallet().Address()) -} - -func (v *LegacyEthereumKeeperRegistry) SetConfigTypeSafe(ocrConfig OCRv2Config) error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - switch v.version { - case ethereum.RegistryVersion_2_1: - tx, err := v.registry2_1.SetConfigTypeSafe(txOpts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.TypedOnchainConfig21, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - tx, err := v.registry2_2.SetConfigTypeSafe(txOpts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.TypedOnchainConfig22, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetConfigTypeSafe is not supported in keeper registry version %d", v.version) - } -} - -func (v *LegacyEthereumKeeperRegistry) SetConfig(config KeeperRegistrySettings, ocrConfig OCRv2Config) error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - callOpts := bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: nil, - } - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err := v.registry1_1.SetConfig( - txOpts, - config.PaymentPremiumPPB, - config.FlatFeeMicroLINK, - config.BlockCountPerTurn, - config.CheckGasLimit, - config.StalenessSeconds, - config.GasCeilingMultiplier, - config.FallbackGasPrice, - config.FallbackLinkPrice, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_2: - state, err := v.registry1_2.GetState(&callOpts) - if err != nil { - return err - } - - tx, err := v.registry1_2.SetConfig(txOpts, keeper_registry_wrapper1_2.Config{ - PaymentPremiumPPB: config.PaymentPremiumPPB, - FlatFeeMicroLink: config.FlatFeeMicroLINK, - BlockCountPerTurn: config.BlockCountPerTurn, - CheckGasLimit: config.CheckGasLimit, - StalenessSeconds: config.StalenessSeconds, - GasCeilingMultiplier: config.GasCeilingMultiplier, - MinUpkeepSpend: config.MinUpkeepSpend, - MaxPerformGas: config.MaxPerformGas, - FallbackGasPrice: config.FallbackGasPrice, - FallbackLinkPrice: config.FallbackLinkPrice, - // Keep the transcoder and registrar same. They have separate setters - Transcoder: state.Config.Transcoder, - Registrar: state.Config.Registrar, - }) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_3: - state, err := v.registry1_3.GetState(&callOpts) - if err != nil { - return err - } - - tx, err := v.registry1_3.SetConfig(txOpts, keeper_registry_wrapper1_3.Config{ - PaymentPremiumPPB: config.PaymentPremiumPPB, - FlatFeeMicroLink: config.FlatFeeMicroLINK, - BlockCountPerTurn: config.BlockCountPerTurn, - CheckGasLimit: config.CheckGasLimit, - StalenessSeconds: config.StalenessSeconds, - GasCeilingMultiplier: config.GasCeilingMultiplier, - MinUpkeepSpend: config.MinUpkeepSpend, - MaxPerformGas: config.MaxPerformGas, - FallbackGasPrice: config.FallbackGasPrice, - FallbackLinkPrice: config.FallbackLinkPrice, - // Keep the transcoder and registrar same. They have separate setters - Transcoder: state.Config.Transcoder, - Registrar: state.Config.Registrar, - }) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - tx, err := v.registry2_0.SetConfig(txOpts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("registry version 2.1 and 2.2 must use setConfigTypeSafe function") - default: - return fmt.Errorf("keeper registry version %d is not supported", v.version) - } -} - -// Pause pauses the registry. -func (v *LegacyEthereumKeeperRegistry) Pause() error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.Pause(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - } - - return fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// Migrate performs a migration of the given upkeep ids to the specific destination passed as parameter. -func (v *LegacyEthereumKeeperRegistry) Migrate(upkeepIDs []*big.Int, destinationAddress common.Address) error { - if v.version != ethereum.RegistryVersion_1_2 { - return fmt.Errorf("migration of upkeeps is only available for version 1.2 of the registries") - } - - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_2.MigrateUpkeeps(txOpts, upkeepIDs, destinationAddress) - if err != nil { - return err - } - - return v.client.ProcessTransaction(tx) -} - -// SetMigrationPermissions sets the permissions of another registry to allow migrations between the two. -func (v *LegacyEthereumKeeperRegistry) SetMigrationPermissions(peerAddress common.Address, permission uint8) error { - if v.version != ethereum.RegistryVersion_1_2 { - return fmt.Errorf("migration of upkeeps is only available for version 1.2 of the registries") - } - - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_2.SetPeerRegistryMigrationPermission(txOpts, peerAddress, permission) - if err != nil { - return err - } - - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumKeeperRegistry) SetRegistrar(registrarAddr string) error { - if v.version == ethereum.RegistryVersion_2_0 { - // we short circuit and exit, so we don't create a new txs messing up the nonce before exiting - return fmt.Errorf("please use set config") - } - - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - callOpts := bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: nil, - } - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err := v.registry1_1.SetRegistrar(txOpts, common.HexToAddress(registrarAddr)) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_2: - state, err := v.registry1_2.GetState(&callOpts) - if err != nil { - return err - } - newConfig := state.Config - newConfig.Registrar = common.HexToAddress(registrarAddr) - tx, err := v.registry1_2.SetConfig(txOpts, newConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_1_3: - state, err := v.registry1_3.GetState(&callOpts) - if err != nil { - return err - } - newConfig := state.Config - newConfig.Registrar = common.HexToAddress(registrarAddr) - tx, err := v.registry1_3.SetConfig(txOpts, newConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("keeper registry version %d is not supported", v.version) - } -} - -// AddUpkeepFunds adds link for particular upkeep id -func (v *LegacyEthereumKeeperRegistry) AddUpkeepFundsFromKey(_ *big.Int, _ *big.Int, _ int) error { - panic("this method is only supported by contracts using Seth client") -} - -// AddUpkeepFunds adds link for particular upkeep id -func (v *LegacyEthereumKeeperRegistry) AddUpkeepFunds(id *big.Int, amount *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.AddFunds(opts, id, amount) - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.AddFunds(opts, id, amount) - } - - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// GetUpkeepInfo gets upkeep info -func (v *LegacyEthereumKeeperRegistry) GetUpkeepInfo(ctx context.Context, id *big.Int) (*UpkeepInfo, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - uk, err := v.registry1_1.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case ethereum.RegistryVersion_1_2: - uk, err := v.registry1_2.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case ethereum.RegistryVersion_1_3: - uk, err := v.registry1_3.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - LastKeeper: uk.LastKeeper.Hex(), - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - }, nil - case ethereum.RegistryVersion_2_0: - uk, err := v.registry2_0.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.ExecuteGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - LastPerformBlockNumber: uk.LastPerformBlockNumber, - AmountSpent: uk.AmountSpent, - Paused: uk.Paused, - OffchainConfig: uk.OffchainConfig, - }, nil - case ethereum.RegistryVersion_2_1: - uk, err := v.registry2_1.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.PerformGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - LastPerformBlockNumber: uk.LastPerformedBlockNumber, - AmountSpent: uk.AmountSpent, - Paused: uk.Paused, - OffchainConfig: uk.OffchainConfig, - }, nil - case ethereum.RegistryVersion_2_2: - return v.getUpkeepInfo22(opts, id) - } - - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -func (v *LegacyEthereumKeeperRegistry) getUpkeepInfo22(opts *bind.CallOpts, id *big.Int) (*UpkeepInfo, error) { - uk, err := v.registry2_2.GetUpkeep(opts, id) - if err != nil { - return nil, err - } - return &UpkeepInfo{ - Target: uk.Target.Hex(), - ExecuteGas: uk.PerformGas, - CheckData: uk.CheckData, - Balance: uk.Balance, - Admin: uk.Admin.Hex(), - MaxValidBlocknumber: uk.MaxValidBlocknumber, - LastPerformBlockNumber: uk.LastPerformedBlockNumber, - AmountSpent: uk.AmountSpent, - Paused: uk.Paused, - OffchainConfig: uk.OffchainConfig, - }, nil -} - -func (v *LegacyEthereumKeeperRegistry) GetKeeperInfo(ctx context.Context, keeperAddr string) (*KeeperInfo, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - var info struct { - Payee common.Address - Active bool - Balance *big.Int - } - var err error - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - info, err = v.registry1_1.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_1_2: - info, err = v.registry1_2.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_1_3: - info, err = v.registry1_3.GetKeeperInfo(opts, common.HexToAddress(keeperAddr)) - case ethereum.RegistryVersion_2_0, ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - // this is not used anywhere - return nil, fmt.Errorf("not supported") - } - - if err != nil { - return nil, err - } - return &KeeperInfo{ - Payee: info.Payee.Hex(), - Active: info.Active, - Balance: info.Balance, - }, nil -} - -func (v *LegacyEthereumKeeperRegistry) SetKeepers(keepers []string, payees []string, ocrConfig OCRv2Config) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - keepersAddresses := make([]common.Address, 0) - for _, k := range keepers { - keepersAddresses = append(keepersAddresses, common.HexToAddress(k)) - } - payeesAddresses := make([]common.Address, 0) - for _, p := range payees { - payeesAddresses = append(payeesAddresses, common.HexToAddress(p)) - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.SetKeepers(opts, keepersAddresses, payeesAddresses) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.SetKeepers(opts, keepersAddresses, payeesAddresses) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.SetKeepers(opts, keepersAddresses, payeesAddresses) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.SetConfig(opts, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("not supported") - } - - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// RegisterUpkeep registers contract to perform upkeep -func (v *LegacyEthereumKeeperRegistry) RegisterUpkeep(target string, gasLimit uint32, admin string, checkData []byte) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - ) - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - ) - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - ) - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.RegisterUpkeep( - opts, - common.HexToAddress(target), - gasLimit, - common.HexToAddress(admin), - checkData, - nil, //offchain config - ) - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return fmt.Errorf("not supported") - } - - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// CancelUpkeep cancels the given upkeep ID -func (v *LegacyEthereumKeeperRegistry) CancelUpkeep(id *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - tx, err = v.registry1_1.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.CancelUpkeep(opts, id) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.CancelUpkeep(opts, id) - if err != nil { - return err - } - } - - v.l.Info(). - Str("Upkeep ID", strconv.FormatInt(id.Int64(), 10)). - Str("From", v.client.GetDefaultWallet().Address()). - Str("TX Hash", tx.Hash().String()). - Msg("Cancel Upkeep tx") - return v.client.ProcessTransaction(tx) -} - -// SetUpkeepGasLimit sets the perform gas limit for a given upkeep ID -func (v *LegacyEthereumKeeperRegistry) SetUpkeepGasLimit(id *big.Int, gas uint32) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - var tx *types.Transaction - - switch v.version { - case ethereum.RegistryVersion_1_2: - tx, err = v.registry1_2.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_1_3: - tx, err = v.registry1_3.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_0: - tx, err = v.registry2_0.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_1: - tx, err = v.registry2_1.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - case ethereum.RegistryVersion_2_2: - tx, err = v.registry2_2.SetUpkeepGasLimit(opts, id, gas) - if err != nil { - return err - } - default: - return fmt.Errorf("keeper registry version %d is not supported for SetUpkeepGasLimit", v.version) - } - return v.client.ProcessTransaction(tx) -} - -// GetKeeperList get list of all registered keeper addresses -func (v *LegacyEthereumKeeperRegistry) GetKeeperList(ctx context.Context) ([]string, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - var list []common.Address - var err error - - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - list, err = v.registry1_1.GetKeeperList(opts) - case ethereum.RegistryVersion_1_2: - state, err := v.registry1_2.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Keepers - case ethereum.RegistryVersion_1_3: - state, err := v.registry1_3.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Keepers - case ethereum.RegistryVersion_2_0: - state, err := v.registry2_0.GetState(opts) - if err != nil { - return []string{}, err - } - list = state.Transmitters - case ethereum.RegistryVersion_2_1, ethereum.RegistryVersion_2_2: - return nil, fmt.Errorf("not supported") - } - - if err != nil { - return []string{}, err - } - addrs := make([]string, 0) - for _, ca := range list { - addrs = append(addrs, ca.Hex()) - } - return addrs, nil -} - -// UpdateCheckData updates the check data of an upkeep -func (v *LegacyEthereumKeeperRegistry) UpdateCheckData(id *big.Int, newCheckData []byte) error { - - switch v.version { - case ethereum.RegistryVersion_1_3: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_3.UpdateCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.UpdateCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepCheckData(opts, id, newCheckData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("UpdateCheckData is not supported by keeper registry version %d", v.version) - } -} - -// SetUpkeepTriggerConfig updates the trigger config of an upkeep (only for version 2.1) -func (v *LegacyEthereumKeeperRegistry) SetUpkeepTriggerConfig(id *big.Int, triggerConfig []byte) error { - - switch v.version { - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepTriggerConfig(opts, id, triggerConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepTriggerConfig(opts, id, triggerConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetUpkeepTriggerConfig is not supported by keeper registry version %d", v.version) - } -} - -// SetUpkeepPrivilegeConfig sets the privilege config of an upkeep (only for version 2.1) -func (v *LegacyEthereumKeeperRegistry) SetUpkeepPrivilegeConfig(id *big.Int, privilegeConfig []byte) error { - - switch v.version { - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepPrivilegeConfig(opts, id, privilegeConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetUpkeepPrivilegeConfig is not supported by keeper registry version %d", v.version) - } -} - -// PauseUpkeep stops an upkeep from an upkeep -func (v *LegacyEthereumKeeperRegistry) PauseUpkeep(id *big.Int) error { - switch v.version { - case ethereum.RegistryVersion_1_3: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_3.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.PauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("PauseUpkeep is not supported by keeper registry version %d", v.version) - } -} - -// UnpauseUpkeep get list of all registered keeper addresses -func (v *LegacyEthereumKeeperRegistry) UnpauseUpkeep(id *big.Int) error { - switch v.version { - case ethereum.RegistryVersion_1_3: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry1_3.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.UnpauseUpkeep(opts, id) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("UnpauseUpkeep is not supported by keeper registry version %d", v.version) - } -} - -func (v *LegacyEthereumKeeperRegistry) SetUpkeepOffchainConfig(id *big.Int, offchainConfig []byte) error { - switch v.version { - case ethereum.RegistryVersion_2_0: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_0.SetUpkeepOffchainConfig(opts, id, offchainConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_1: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_1.SetUpkeepOffchainConfig(opts, id, offchainConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - case ethereum.RegistryVersion_2_2: - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.registry2_2.SetUpkeepOffchainConfig(opts, id, offchainConfig) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) - default: - return fmt.Errorf("SetUpkeepOffchainConfig is not supported by keeper registry version %d", v.version) - } -} - -// Parses upkeep performed log -func (v *LegacyEthereumKeeperRegistry) ParseUpkeepPerformedLog(log *types.Log) (*UpkeepPerformedLog, error) { - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - parsedLog, err := v.registry1_1.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case ethereum.RegistryVersion_1_2: - parsedLog, err := v.registry1_2.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case ethereum.RegistryVersion_1_3: - parsedLog, err := v.registry1_3.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: parsedLog.From, - }, nil - case ethereum.RegistryVersion_2_0: - parsedLog, err := v.registry2_0.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: utils.ZeroAddress, - }, nil - case ethereum.RegistryVersion_2_1: - parsedLog, err := v.registry2_1.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: utils.ZeroAddress, - }, nil - case ethereum.RegistryVersion_2_2: - parsedLog, err := v.registry2_2.ParseUpkeepPerformed(*log) - if err != nil { - return nil, err - } - return &UpkeepPerformedLog{ - Id: parsedLog.Id, - Success: parsedLog.Success, - From: utils.ZeroAddress, - }, nil - } - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// ParseStaleUpkeepReportLog Parses Stale upkeep report log -func (v *LegacyEthereumKeeperRegistry) ParseStaleUpkeepReportLog(log *types.Log) (*StaleUpkeepReportLog, error) { - //nolint:exhaustive - switch v.version { - case ethereum.RegistryVersion_2_0: - parsedLog, err := v.registry2_0.ParseStaleUpkeepReport(*log) - if err != nil { - return nil, err - } - return &StaleUpkeepReportLog{ - Id: parsedLog.Id, - }, nil - case ethereum.RegistryVersion_2_1: - parsedLog, err := v.registry2_1.ParseStaleUpkeepReport(*log) - if err != nil { - return nil, err - } - return &StaleUpkeepReportLog{ - Id: parsedLog.Id, - }, nil - case ethereum.RegistryVersion_2_2: - parsedLog, err := v.registry2_2.ParseStaleUpkeepReport(*log) - if err != nil { - return nil, err - } - return &StaleUpkeepReportLog{ - Id: parsedLog.Id, - }, nil - } - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// Parses the upkeep ID from an 'UpkeepRegistered' log, returns error on any other log -func (v *LegacyEthereumKeeperRegistry) ParseUpkeepIdFromRegisteredLog(log *types.Log) (*big.Int, error) { - switch v.version { - case ethereum.RegistryVersion_1_0, ethereum.RegistryVersion_1_1: - parsedLog, err := v.registry1_1.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_1_2: - parsedLog, err := v.registry1_2.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_1_3: - parsedLog, err := v.registry1_3.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_2_0: - parsedLog, err := v.registry2_0.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_2_1: - parsedLog, err := v.registry2_1.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - case ethereum.RegistryVersion_2_2: - parsedLog, err := v.registry2_2.ParseUpkeepRegistered(*log) - if err != nil { - return nil, err - } - return parsedLog.Id, nil - } - - return nil, fmt.Errorf("keeper registry version %d is not supported", v.version) -} - -// KeeperConsumerRoundConfirmer is a header subscription that awaits for a round of upkeeps -type KeeperConsumerRoundConfirmer struct { - instance KeeperConsumer - upkeepsValue int - doneChan chan struct{} - context context.Context - cancel context.CancelFunc - l zerolog.Logger -} - -// NewKeeperConsumerRoundConfirmer provides a new instance of a KeeperConsumerRoundConfirmer -func NewKeeperConsumerRoundConfirmer( - contract KeeperConsumer, - counterValue int, - timeout time.Duration, - logger zerolog.Logger, -) *KeeperConsumerRoundConfirmer { - ctx, ctxCancel := context.WithTimeout(context.Background(), timeout) - return &KeeperConsumerRoundConfirmer{ - instance: contract, - upkeepsValue: counterValue, - doneChan: make(chan struct{}), - context: ctx, - cancel: ctxCancel, - l: logger, - } -} - -// ReceiveHeader will query the latest Keeper round and check to see whether the round has confirmed -func (o *KeeperConsumerRoundConfirmer) ReceiveHeader(_ blockchain.NodeHeader) error { - upkeeps, err := o.instance.Counter(context.Background()) - if err != nil { - return err - } - l := o.l.Info(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps", upkeeps.Int64()). - Int("Required upkeeps", o.upkeepsValue) - if upkeeps.Int64() == int64(o.upkeepsValue) { - l.Msg("Upkeep completed") - o.doneChan <- struct{}{} - } else { - l.Msg("Waiting for upkeep round") - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *KeeperConsumerRoundConfirmer) Wait() error { - for { - select { - case <-o.doneChan: - o.cancel() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for upkeeps to confirm: %d", o.upkeepsValue) - } - } -} - -// KeeperConsumerPerformanceRoundConfirmer is a header subscription that awaits for a round of upkeeps -type KeeperConsumerPerformanceRoundConfirmer struct { - instance KeeperConsumerPerformance - doneChan chan bool - context context.Context - cancel context.CancelFunc - - lastBlockNum uint64 // Records the number of the last block that came in - blockCadence int64 // How many blocks before an upkeep should happen - blockRange int64 // How many blocks to watch upkeeps for - blocksSinceSubscription int64 // How many blocks have passed since subscribing - expectedUpkeepCount int64 // The count of upkeeps expected next iteration - blocksSinceSuccessfulUpkeep int64 // How many blocks have come in since the last successful upkeep - allMissedUpkeeps []int64 // Tracks the amount of blocks missed in each missed upkeep - totalSuccessfulUpkeeps int64 - - metricsReporter *testreporters.KeeperBlockTimeTestReporter // Testreporter to track results - complete bool - l zerolog.Logger -} - -// NewKeeperConsumerPerformanceRoundConfirmer provides a new instance of a KeeperConsumerPerformanceRoundConfirmer -// Used to track and log performance test results for keepers -func NewKeeperConsumerPerformanceRoundConfirmer( - contract KeeperConsumerPerformance, - expectedBlockCadence int64, // Expected to upkeep every 5/10/20 blocks, for example - blockRange int64, - metricsReporter *testreporters.KeeperBlockTimeTestReporter, - logger zerolog.Logger, -) *KeeperConsumerPerformanceRoundConfirmer { - ctx, cancelFunc := context.WithCancel(context.Background()) - return &KeeperConsumerPerformanceRoundConfirmer{ - instance: contract, - doneChan: make(chan bool), - context: ctx, - cancel: cancelFunc, - blockCadence: expectedBlockCadence, - blockRange: blockRange, - blocksSinceSubscription: 0, - blocksSinceSuccessfulUpkeep: 0, - expectedUpkeepCount: 1, - allMissedUpkeeps: []int64{}, - totalSuccessfulUpkeeps: 0, - metricsReporter: metricsReporter, - complete: false, - lastBlockNum: 0, - l: logger, - } -} - -// ReceiveHeader will query the latest Keeper round and check to see whether the round has confirmed -func (o *KeeperConsumerPerformanceRoundConfirmer) ReceiveHeader(receivedHeader blockchain.NodeHeader) error { - if receivedHeader.Number.Uint64() <= o.lastBlockNum { // Uncle / reorg we won't count - return nil - } - o.lastBlockNum = receivedHeader.Number.Uint64() - // Increment block counters - o.blocksSinceSubscription++ - o.blocksSinceSuccessfulUpkeep++ - upkeepCount, err := o.instance.GetUpkeepCount(context.Background()) - if err != nil { - return err - } - - isEligible, err := o.instance.CheckEligible(context.Background()) - if err != nil { - return err - } - if isEligible { - o.l.Trace(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Msg("Upkeep Now Eligible") - } - if upkeepCount.Int64() >= o.expectedUpkeepCount { // Upkeep was successful - if o.blocksSinceSuccessfulUpkeep < o.blockCadence { // If there's an early upkeep, that's weird - o.l.Error(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Actual Cadence", o.blocksSinceSuccessfulUpkeep). - Err(errors.New("found an early Upkeep")) - return fmt.Errorf("found an early Upkeep on contract %s", o.instance.Address()) - } else if o.blocksSinceSuccessfulUpkeep == o.blockCadence { // Perfectly timed upkeep - o.l.Info(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Actual Cadence", o.blocksSinceSuccessfulUpkeep). - Msg("Successful Upkeep on Expected Cadence") - o.totalSuccessfulUpkeeps++ - } else { // Late upkeep - o.l.Warn(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Actual Cadence", o.blocksSinceSuccessfulUpkeep). - Msg("Upkeep Completed Late") - o.allMissedUpkeeps = append(o.allMissedUpkeeps, o.blocksSinceSuccessfulUpkeep-o.blockCadence) - } - // Update upkeep tracking values - o.blocksSinceSuccessfulUpkeep = 0 - o.expectedUpkeepCount++ - } - - if o.blocksSinceSubscription > o.blockRange { - if o.blocksSinceSuccessfulUpkeep > o.blockCadence { - o.l.Warn(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Expected Cadence", o.blockCadence). - Int64("Expected Upkeep Count", o.expectedUpkeepCount). - Int64("Blocks Waiting", o.blocksSinceSuccessfulUpkeep). - Int64("Total Blocks Watched", o.blocksSinceSubscription). - Msg("Finished Watching for Upkeeps While Waiting on a Late Upkeep") - o.allMissedUpkeeps = append(o.allMissedUpkeeps, o.blocksSinceSuccessfulUpkeep-o.blockCadence) - } else { - o.l.Info(). - Str("Contract Address", o.instance.Address()). - Int64("Upkeeps Performed", upkeepCount.Int64()). - Int64("Total Blocks Watched", o.blocksSinceSubscription). - Msg("Finished Watching for Upkeeps") - } - o.doneChan <- true - o.complete = true - return nil - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *KeeperConsumerPerformanceRoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - o.logDetails() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for expected upkeep count to confirm: %d", o.expectedUpkeepCount) - } - } -} - -func (o *KeeperConsumerPerformanceRoundConfirmer) Complete() bool { - return o.complete -} - -func (o *KeeperConsumerPerformanceRoundConfirmer) logDetails() { - report := testreporters.KeeperBlockTimeTestReport{ - ContractAddress: o.instance.Address(), - TotalExpectedUpkeeps: o.blockRange / o.blockCadence, - TotalSuccessfulUpkeeps: o.totalSuccessfulUpkeeps, - AllMissedUpkeeps: o.allMissedUpkeeps, - } - o.metricsReporter.ReportMutex.Lock() - o.metricsReporter.Reports = append(o.metricsReporter.Reports, report) - defer o.metricsReporter.ReportMutex.Unlock() -} - -// LegacyKeeperConsumerBenchmarkRoundConfirmer is a header subscription that awaits for a round of upkeeps -type LegacyKeeperConsumerBenchmarkRoundConfirmer struct { - instance AutomationConsumerBenchmark - registry KeeperRegistry - upkeepID *big.Int - doneChan chan bool - context context.Context - cancel context.CancelFunc - - firstBlockNum uint64 // Records the number of the first block that came in - lastBlockNum uint64 // Records the number of the last block that came in - blockRange int64 // How many blocks to watch upkeeps for - upkeepSLA int64 // SLA after which an upkeep is counted as 'missed' - metricsReporter *testreporters.KeeperBenchmarkTestReporter // Testreporter to track results - upkeepIndex int64 - firstEligibleBuffer int64 - - // State variables, changes as we get blocks - blocksSinceSubscription int64 // How many blocks have passed since subscribing - blocksSinceEligible int64 // How many blocks have come in since upkeep has been eligible for check - countEligible int64 // Number of times the upkeep became eligible - countMissed int64 // Number of times we missed SLA for performing upkeep - upkeepCount int64 // The count of upkeeps done so far - allCheckDelays []int64 // Tracks the amount of blocks missed before an upkeep since it became eligible - complete bool - l zerolog.Logger -} - -// NewLegacyKeeperConsumerBenchmarkRoundConfirmer provides a new instance of a LegacyKeeperConsumerBenchmarkRoundConfirmer -// Used to track and log benchmark test results for keepers -func NewLegacyKeeperConsumerBenchmarkRoundConfirmer( - contract AutomationConsumerBenchmark, - registry KeeperRegistry, - upkeepID *big.Int, - blockRange int64, - upkeepSLA int64, - metricsReporter *testreporters.KeeperBenchmarkTestReporter, - upkeepIndex int64, - firstEligibleBuffer int64, - logger zerolog.Logger, -) *LegacyKeeperConsumerBenchmarkRoundConfirmer { - ctx, cancelFunc := context.WithCancel(context.Background()) - return &LegacyKeeperConsumerBenchmarkRoundConfirmer{ - instance: contract, - registry: registry, - upkeepID: upkeepID, - doneChan: make(chan bool), - context: ctx, - cancel: cancelFunc, - blockRange: blockRange, - upkeepSLA: upkeepSLA, - blocksSinceSubscription: 0, - blocksSinceEligible: 0, - upkeepCount: 0, - allCheckDelays: []int64{}, - metricsReporter: metricsReporter, - complete: false, - lastBlockNum: 0, - upkeepIndex: upkeepIndex, - firstBlockNum: 0, - firstEligibleBuffer: firstEligibleBuffer, - l: logger, - } -} - -// ReceiveHeader will query the latest Keeper round and check to see whether the round has confirmed -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) ReceiveHeader(receivedHeader blockchain.NodeHeader) error { - if receivedHeader.Number.Uint64() <= o.lastBlockNum { // Uncle / reorg we won't count - return nil - } - if o.firstBlockNum == 0 { - o.firstBlockNum = receivedHeader.Number.Uint64() - } - o.lastBlockNum = receivedHeader.Number.Uint64() - // Increment block counters - o.blocksSinceSubscription++ - - upkeepCount, err := o.instance.GetUpkeepCount(context.Background(), big.NewInt(o.upkeepIndex)) - if err != nil { - return err - } - - if upkeepCount.Int64() > o.upkeepCount { // A new upkeep was done - if upkeepCount.Int64() != o.upkeepCount+1 { - return errors.New("upkeep count increased by more than 1 in a single block") - } - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Upkeep_Count", upkeepCount.Int64()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep Performed") - - if o.blocksSinceEligible > o.upkeepSLA { - o.l.Warn(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep Missed SLA") - o.countMissed++ - } - - o.allCheckDelays = append(o.allCheckDelays, o.blocksSinceEligible) - o.upkeepCount++ - o.blocksSinceEligible = 0 - } - - isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), big.NewInt(o.blockRange), big.NewInt(o.firstEligibleBuffer)) - if err != nil { - return err - } - if isEligible { - if o.blocksSinceEligible == 0 { - // First time this upkeep became eligible - o.countEligible++ - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep Now Eligible") - } - o.blocksSinceEligible++ - } - - if o.blocksSinceSubscription >= o.blockRange || int64(o.lastBlockNum-o.firstBlockNum) >= o.blockRange { - if o.blocksSinceEligible > 0 { - if o.blocksSinceEligible > o.upkeepSLA { - o.l.Warn(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep remained eligible at end of test and missed SLA") - o.countMissed++ - } else { - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Upkeep_Count", upkeepCount.Int64()). - Int64("Blocks_since_eligible", o.blocksSinceEligible). - Str("Registry_Address", o.registry.Address()). - Msg("Upkeep remained eligible at end of test and was within SLA") - } - o.allCheckDelays = append(o.allCheckDelays, o.blocksSinceEligible) - } - - o.l.Info(). - Uint64("Block_Number", receivedHeader.Number.Uint64()). - Str("Upkeep_ID", o.upkeepID.String()). - Str("Contract_Address", o.instance.Address()). - Int64("Upkeeps_Performed", upkeepCount.Int64()). - Int64("Total_Blocks_Watched", o.blocksSinceSubscription). - Str("Registry_Address", o.registry.Address()). - Msg("Finished Watching for Upkeeps") - - o.doneChan <- true - o.complete = true - return nil - } - return nil -} - -// Wait is a blocking function that will wait until the round has confirmed, and timeout if the deadline has passed -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) Wait() error { - defer func() { o.complete = true }() - for { - select { - case <-o.doneChan: - o.cancel() - o.logDetails() - return nil - case <-o.context.Done(): - return fmt.Errorf("timeout waiting for expected number of blocks: %d", o.blockRange) - } - } -} - -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) Complete() bool { - return o.complete -} - -func (o *LegacyKeeperConsumerBenchmarkRoundConfirmer) logDetails() { - report := testreporters.KeeperBenchmarkTestReport{ - ContractAddress: o.instance.Address(), - TotalEligibleCount: o.countEligible, - TotalSLAMissedUpkeeps: o.countMissed, - TotalPerformedUpkeeps: o.upkeepCount, - AllCheckDelays: o.allCheckDelays, - RegistryAddress: o.registry.Address(), - } - o.metricsReporter.ReportMutex.Lock() - o.metricsReporter.Reports = append(o.metricsReporter.Reports, report) - defer o.metricsReporter.ReportMutex.Unlock() -} - -// LegacyEthereumUpkeepCounter represents keeper consumer (upkeep) counter contract -type LegacyEthereumUpkeepCounter struct { - client blockchain.EVMClient - consumer *upkeep_counter_wrapper.UpkeepCounter - address *common.Address -} - -func (v *LegacyEthereumUpkeepCounter) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumUpkeepCounter) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} -func (v *LegacyEthereumUpkeepCounter) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -func (v *LegacyEthereumUpkeepCounter) SetSpread(testRange *big.Int, interval *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetSpread(opts, testRange, interval) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// Just pass for non-logtrigger -func (v *LegacyEthereumUpkeepCounter) Start() error { - return nil -} - -// LegacyEthereumUpkeepPerformCounterRestrictive represents keeper consumer (upkeep) counter contract -type LegacyEthereumUpkeepPerformCounterRestrictive struct { - client blockchain.EVMClient - consumer *upkeep_perform_counter_restrictive_wrapper.UpkeepPerformCounterRestrictive - address *common.Address -} - -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - count, err := v.consumer.GetCountPerforms(opts) - return count, err -} - -func (v *LegacyEthereumUpkeepPerformCounterRestrictive) SetSpread(testRange *big.Int, interval *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetSpread(opts, testRange, interval) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// EthereumKeeperConsumer represents keeper consumer (upkeep) contract -type EthereumKeeperConsumer struct { - client blockchain.EVMClient - consumer *keeper_consumer_wrapper.KeeperConsumer - address *common.Address -} - -// Just pass for non-logtrigger -func (v *EthereumKeeperConsumer) Start() error { - return nil -} - -func (v *EthereumKeeperConsumer) Address() string { - return v.address.Hex() -} - -func (v *EthereumKeeperConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationStreamsLookupUpkeepConsumer struct { - client blockchain.EVMClient - consumer *streams_lookup_upkeep_wrapper.StreamsLookupUpkeep - address *common.Address -} - -func (v *LegacyEthereumAutomationStreamsLookupUpkeepConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationStreamsLookupUpkeepConsumer) Start() error { - // For this consumer upkeep, we use this Start() function to set ParamKeys so as to run mercury v0.2 - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - // The default values of ParamKeys are "feedIDs" and "timestamp" which are for v0.3 - tx, err := v.consumer.SetParamKeys(txOpts, "feedIdHex", "blockNumber") - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumAutomationStreamsLookupUpkeepConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer struct { - client blockchain.EVMClient - consumer *log_triggered_streams_lookup_wrapper.LogTriggeredStreamsLookup - address *common.Address -} - -func (v *LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer) Address() string { - return v.address.Hex() -} - -// Kick off the log trigger event. The contract uses Mercury v0.2 so no need to set ParamKeys -func (v *LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer) Start() error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.consumer.Start(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumAutomationLogTriggeredStreamsLookupUpkeepConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationLogCounterConsumer struct { - client blockchain.EVMClient - consumer *log_upkeep_counter_wrapper.LogUpkeepCounter - address *common.Address -} - -func (v *LegacyEthereumAutomationLogCounterConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationLogCounterConsumer) Start() error { - txOpts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - - tx, err := v.consumer.Start(txOpts) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumAutomationLogCounterConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -type LegacyEthereumAutomationSimpleLogCounterConsumer struct { - client blockchain.EVMClient - consumer *simple_log_upkeep_counter_wrapper.SimpleLogUpkeepCounter - address *common.Address -} - -func (v *LegacyEthereumAutomationSimpleLogCounterConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationSimpleLogCounterConsumer) Start() error { - return nil -} - -func (v *LegacyEthereumAutomationSimpleLogCounterConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.consumer.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -// LegacyEthereumKeeperConsumerPerformance represents a more complicated keeper consumer contract, one intended only for -// performance tests. -type LegacyEthereumKeeperConsumerPerformance struct { - client blockchain.EVMClient - consumer *keeper_consumer_performance_wrapper.KeeperConsumerPerformance - address *common.Address -} - -func (v *LegacyEthereumKeeperConsumerPerformance) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperConsumerPerformance) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} - -func (v *LegacyEthereumKeeperConsumerPerformance) CheckEligible(ctx context.Context) (bool, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.CheckEligible(opts) - return eligible, err -} - -func (v *LegacyEthereumKeeperConsumerPerformance) GetUpkeepCount(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.GetCountPerforms(opts) - return eligible, err -} - -func (v *LegacyEthereumKeeperConsumerPerformance) SetCheckGasToBurn(_ context.Context, gas *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetCheckGasToBurn(opts, gas) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -func (v *LegacyEthereumKeeperConsumerPerformance) SetPerformGasToBurn(_ context.Context, gas *big.Int) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.consumer.SetPerformGasToBurn(opts, gas) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// LegacyEthereumKeeperPerformDataCheckerConsumer represents keeper perform data checker contract -type LegacyEthereumKeeperPerformDataCheckerConsumer struct { - client blockchain.EVMClient - performDataChecker *perform_data_checker_wrapper.PerformDataChecker - address *common.Address -} - -func (v *LegacyEthereumKeeperPerformDataCheckerConsumer) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperPerformDataCheckerConsumer) Counter(ctx context.Context) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - cnt, err := v.performDataChecker.Counter(opts) - if err != nil { - return nil, err - } - return cnt, nil -} - -func (v *LegacyEthereumKeeperPerformDataCheckerConsumer) SetExpectedData(_ context.Context, expectedData []byte) error { - opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) - if err != nil { - return err - } - tx, err := v.performDataChecker.SetExpectedData(opts, expectedData) - if err != nil { - return err - } - return v.client.ProcessTransaction(tx) -} - -// LegacyEthereumAutomationConsumerBenchmark represents a more complicated keeper consumer contract, one intended only for -// Benchmark tests. -type LegacyEthereumAutomationConsumerBenchmark struct { - client blockchain.EVMClient - consumer *automation_consumer_benchmark.AutomationConsumerBenchmark - address *common.Address -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) CheckEligible(ctx context.Context, id *big.Int, _range *big.Int, firstEligibleBuffer *big.Int) (bool, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.CheckEligible(opts, id, _range, firstEligibleBuffer) - return eligible, err -} - -func (v *LegacyEthereumAutomationConsumerBenchmark) GetUpkeepCount(ctx context.Context, id *big.Int) (*big.Int, error) { - opts := &bind.CallOpts{ - From: common.HexToAddress(v.client.GetDefaultWallet().Address()), - Context: ctx, - } - eligible, err := v.consumer.GetCountPerforms(opts, id) - return eligible, err -} - -// LegacyEthereumKeeperRegistrar corresponds to the registrar which is used to send requests to the registry when -// registering new upkeeps. -type LegacyEthereumKeeperRegistrar struct { - client blockchain.EVMClient - registrar *keeper_registrar_wrapper1_2.KeeperRegistrar - registrar20 *keeper_registrar_wrapper2_0.KeeperRegistrar - registrar21 *registrar21.AutomationRegistrar - address *common.Address -} - -func (v *LegacyEthereumKeeperRegistrar) Address() string { - return v.address.Hex() -} - -func (v *LegacyEthereumKeeperRegistrar) Fund(ethAmount *big.Float) error { - gasEstimates, err := v.client.EstimateGas(geth.CallMsg{}) - if err != nil { - return err - } - return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) -} - -// EncodeRegisterRequest encodes register request to call it through link token TransferAndCall -func (v *LegacyEthereumKeeperRegistrar) EncodeRegisterRequest(name string, email []byte, upkeepAddr string, gasLimit uint32, adminAddr string, checkData []byte, amount *big.Int, source uint8, senderAddr string, isLogTrigger bool, isMercury bool) ([]byte, error) { - if v.registrar20 != nil { - registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper2_0.KeeperRegistrarMetaData.ABI)) - if err != nil { - return nil, err - } - req, err := registryABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - checkData, - []byte{}, //offchainConfig - amount, - common.HexToAddress(senderAddr), - ) - - if err != nil { - return nil, err - } - return req, nil - } else if v.registrar21 != nil { - if isLogTrigger { - var topic0InBytes [32]byte - // bytes representation of 0x0000000000000000000000000000000000000000000000000000000000000000 - bytes0 := [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, 0, - } - if isMercury { - // bytes representation of 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd - topic0InBytes = [32]byte{209, 255, 233, 228, 85, 129, 193, 29, 125, 159, 46, 213, 247, 82, 23, 205, 75, 233, 248, 183, 238, 230, 175, 15, 109, 3, 244, 109, 229, 57, 86, 205} - } else { - // bytes representation of 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d - topic0InBytes = [32]byte{ - 61, 83, 163, 149, 80, 224, 70, 136, - 6, 88, 39, 243, 187, 134, 88, 76, - 176, 7, 171, 158, 188, 167, 235, - 213, 40, 231, 48, 28, 156, 49, 235, 93, - } - } - - logTriggerConfigStruct := ac.IAutomationV21PlusCommonLogTriggerConfig{ - ContractAddress: common.HexToAddress(upkeepAddr), - FilterSelector: 0, - Topic0: topic0InBytes, - Topic1: bytes0, - Topic2: bytes0, - Topic3: bytes0, - } - encodedLogTriggerConfig, err := compatibleUtils.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct) - if err != nil { - return nil, err - } - - req, err := registrarABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - uint8(1), // trigger type - checkData, - encodedLogTriggerConfig, // triggerConfig - []byte{}, // offchainConfig - amount, - common.HexToAddress(senderAddr), - ) - - return req, err - } - req, err := registrarABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - uint8(0), // trigger type - checkData, - []byte{}, // triggerConfig - []byte{}, // offchainConfig - amount, - common.HexToAddress(senderAddr), - ) - return req, err - } - registryABI, err := abi.JSON(strings.NewReader(keeper_registrar_wrapper1_2.KeeperRegistrarMetaData.ABI)) - if err != nil { - return nil, err - } - req, err := registryABI.Pack( - "register", - name, - email, - common.HexToAddress(upkeepAddr), - gasLimit, - common.HexToAddress(adminAddr), - checkData, - amount, - source, - common.HexToAddress(senderAddr), - ) - if err != nil { - return nil, err - } - return req, nil +// KeeperRegistrarSettings represents settings for registrar contract +type KeeperRegistrarSettings struct { + AutoApproveConfigType uint8 + AutoApproveMaxAllowed uint16 + RegistryAddr string + MinLinkJuels *big.Int + WETHTokenAddr string } -// LegacyEthereumUpkeepTranscoder represents the transcoder which is used to perform migrations -// of upkeeps from one registry to another. -type LegacyEthereumUpkeepTranscoder struct { - client blockchain.EVMClient - transcoder *upkeep_transcoder.UpkeepTranscoder - address *common.Address +// KeeperInfo keeper status and balance info +type KeeperInfo struct { + Payee string + Active bool + Balance *big.Int } -func (v *LegacyEthereumUpkeepTranscoder) Address() string { - return v.address.Hex() +// UpkeepInfo keeper target info +type UpkeepInfo struct { + Target string + ExecuteGas uint32 + CheckData []byte + Balance *big.Int + LastKeeper string + Admin string + MaxValidBlocknumber uint64 + LastPerformBlockNumber uint32 + AmountSpent *big.Int + Paused bool + OffchainConfig []byte } diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index 7b79ca0173..d4757fa869 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -6,6 +6,9 @@ import ( "math/big" "time" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog/log" @@ -394,7 +397,7 @@ func (v *EthereumVRFConsumer) Address() string { } func (v *EthereumVRFConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } // RequestRandomness requests VRF randomness @@ -421,7 +424,7 @@ func (v *EthereumVRFConsumer) RandomnessOutput(ctx context.Context) (*big.Int, e // Fund sends specified currencies to the contract func (v *EthereumVRF) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } // ProofLength returns the PROOFLENGTH call from the VRF contract @@ -431,3 +434,66 @@ func (v *EthereumVRF) ProofLength(ctx context.Context) (*big.Int, error) { Context: ctx, }) } + +func LoadVRFCoordinatorV2_5(seth *seth.Client, addr string) (VRFCoordinatorV2_5, error) { + address := common.HexToAddress(addr) + abi, err := vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.GetAbi() + if err != nil { + return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to get VRFCoordinatorV2_5 ABI: %w", err) + } + seth.ContractStore.AddABI("VRFCoordinatorV2_5", *abi) + seth.ContractStore.AddBIN("VRFCoordinatorV2_5", common.FromHex(vrf_coordinator_v2_5.VRFCoordinatorV25MetaData.Bin)) + + contract, err := vrf_coordinator_v2_5.NewVRFCoordinatorV25(address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumVRFCoordinatorV2_5{}, fmt.Errorf("failed to instantiate VRFCoordinatorV2_5 instance: %w", err) + } + + return &EthereumVRFCoordinatorV2_5{ + client: seth, + address: address, + coordinator: contract, + }, nil +} + +func LoadBlockHashStore(seth *seth.Client, addr string) (BlockHashStore, error) { + address := common.HexToAddress(addr) + abi, err := blockhash_store.BlockhashStoreMetaData.GetAbi() + if err != nil { + return &EthereumBlockhashStore{}, fmt.Errorf("failed to get BlockHashStore ABI: %w", err) + } + seth.ContractStore.AddABI("BlockHashStore", *abi) + seth.ContractStore.AddBIN("BlockHashStore", common.FromHex(blockhash_store.BlockhashStoreMetaData.Bin)) + + contract, err := blockhash_store.NewBlockhashStore(address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumBlockhashStore{}, fmt.Errorf("failed to instantiate BlockHashStore instance: %w", err) + } + + return &EthereumBlockhashStore{ + client: seth, + address: &address, + blockHashStore: contract, + }, nil +} + +func LoadVRFv2PlusLoadTestConsumer(seth *seth.Client, addr string) (VRFv2PlusLoadTestConsumer, error) { + address := common.HexToAddress(addr) + abi, err := vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.GetAbi() + if err != nil { + return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to get VRFV2PlusLoadTestWithMetrics ABI: %w", err) + } + seth.ContractStore.AddABI("VRFV2PlusLoadTestWithMetrics", *abi) + seth.ContractStore.AddBIN("VRFV2PlusLoadTestWithMetrics", common.FromHex(vrf_v2plus_load_test_with_metrics.VRFV2PlusLoadTestWithMetricsMetaData.Bin)) + + contract, err := vrf_v2plus_load_test_with_metrics.NewVRFV2PlusLoadTestWithMetrics(address, wrappers.MustNewWrappedContractBackend(nil, seth)) + if err != nil { + return &EthereumVRFv2PlusLoadTestConsumer{}, fmt.Errorf("failed to instantiate VRFV2PlusLoadTestWithMetrics instance: %w", err) + } + + return &EthereumVRFv2PlusLoadTestConsumer{ + client: seth, + address: address, + consumer: contract, + }, nil +} diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index be588ea3e3..a9d1a93769 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -804,7 +804,7 @@ func (v *EthereumVRFConsumerV2) GasAvailable() (*big.Int, error) { } func (v *EthereumVRFConsumerV2) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } // RequestRandomness request VRFv2 random words @@ -1028,7 +1028,7 @@ func (v *EthereumVRFV2WrapperLoadTestConsumer) Address() string { } func (v *EthereumVRFV2WrapperLoadTestConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } func (v *EthereumVRFV2WrapperLoadTestConsumer) RequestRandomness(coordinator Coordinator, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*CoordinatorRandomWordsRequested, error) { diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 882baafcd1..9f6f6665d2 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -1121,7 +1121,7 @@ func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) Address() string { } func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) Fund(_ *big.Float) error { - panic("do not use this function, use actions_seth.SendFunds() instead, otherwise we will have to deal with circular dependencies") + panic("do not use this function, use actions.SendFunds() instead, otherwise we will have to deal with circular dependencies") } func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomness( diff --git a/integration-tests/contracts/multicall.go b/integration-tests/contracts/multicall.go index be1af13cce..6b73aed084 100644 --- a/integration-tests/contracts/multicall.go +++ b/integration-tests/contracts/multicall.go @@ -1,8 +1,6 @@ package contracts import ( - "context" - "fmt" "math/big" "strings" @@ -10,11 +8,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog/log" "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" ) @@ -41,19 +36,6 @@ type Result struct { ReturnData []byte } -func WaitForSuccessfulTxMined(evmClient blockchain.EVMClient, tx *types.Transaction) error { - log.Debug().Str("tx", tx.Hash().Hex()).Msg("waiting for tx to be mined") - receipt, err := bind.WaitMined(context.Background(), evmClient.DeployBackend(), tx) - if err != nil { - return err - } - if receipt.Status != types.ReceiptStatusSuccessful { - return fmt.Errorf("tx failed %s", tx.Hash().Hex()) - } - log.Debug().Str("tx", tx.Hash().Hex()).Str("Network", evmClient.GetNetworkName()).Msg("tx mined successfully") - return nil -} - func MultiCallLogTriggerLoadGen( client *seth.Client, multiCallAddress string, diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go index 25b87bcc5b..85e76054c7 100644 --- a/integration-tests/contracts/test_contracts.go +++ b/integration-tests/contracts/test_contracts.go @@ -1,105 +1,123 @@ package contracts import ( + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" + "github.com/smartcontractkit/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" ) -type LegacyLogEmitterContract struct { +type LogEmitterContract struct { address common.Address - client blockchain.EVMClient + client *seth.Client instance *le.LogEmitter l zerolog.Logger } -func (e *LegacyLogEmitterContract) Address() common.Address { +func (e *LogEmitterContract) Address() common.Address { return e.address } -func (e *LegacyLogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } +func (e *LogEmitterContract) EmitLogIntsFromKey(ints []int, keyNum int) (*types.Transaction, error) { bigInts := make([]*big.Int, len(ints)) for i, v := range ints { bigInts[i] = big.NewInt(int64(v)) } - tx, err := e.instance.EmitLog1(opts, bigInts) + tx, err := e.client.Decode(e.instance.EmitLog1(e.client.NewTXKeyOpts(keyNum), bigInts)) if err != nil { return nil, err } - return tx, e.client.ProcessTransaction(tx) + + return tx.Transaction, nil } -func (e *LegacyLogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } +func (e *LogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) { + return e.EmitLogIntsFromKey(ints, 0) +} + +func (e *LogEmitterContract) EmitLogIntsIndexedFromKey(ints []int, keyNum int) (*types.Transaction, error) { bigInts := make([]*big.Int, len(ints)) for i, v := range ints { bigInts[i] = big.NewInt(int64(v)) } - tx, err := e.instance.EmitLog2(opts, bigInts) + tx, err := e.client.Decode(e.instance.EmitLog2(e.client.NewTXKeyOpts(keyNum), bigInts)) if err != nil { return nil, err } - return tx, e.client.ProcessTransaction(tx) + + return tx.Transaction, nil } -func (e *LegacyLogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) - if err != nil { - return nil, err - } - tx, err := e.instance.EmitLog4(opts, big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count))) - if err != nil { - return nil, err - } - return tx, e.client.ProcessTransaction(tx) +func (e *LogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) { + return e.EmitLogIntsIndexedFromKey(ints, 0) } -func (e *LegacyLogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { - opts, err := e.client.TransactionOpts(e.client.GetDefaultWallet()) +func (e *LogEmitterContract) EmitLogIntMultiIndexedFromKey(ints int, ints2 int, count int, keyNum int) (*types.Transaction, error) { + tx, err := e.client.Decode(e.instance.EmitLog4(e.client.NewTXKeyOpts(keyNum), big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count)))) if err != nil { return nil, err } - tx, err := e.instance.EmitLog3(opts, strings) + + return tx.Transaction, nil +} + +func (e *LogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { + return e.EmitLogIntMultiIndexedFromKey(ints, ints2, count, 0) +} + +func (e *LogEmitterContract) EmitLogStringsFromKey(strings []string, keyNum int) (*types.Transaction, error) { + tx, err := e.client.Decode(e.instance.EmitLog3(e.client.NewTXKeyOpts(keyNum), strings)) if err != nil { return nil, err } - return tx, e.client.ProcessTransaction(tx) + return tx.Transaction, nil } -func (e *LegacyLogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) { +func (e *LogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { + return e.EmitLogStringsFromKey(strings, 0) +} + +func (e *LogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) { return e.EmitLogInts([]int{payload}) } -func (e *LegacyLogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) { +func (e *LogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) { return e.EmitLogIntsIndexed([]int{payload}) } -func (e *LegacyLogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) { +func (e *LogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) { return e.EmitLogStrings([]string{strings}) } -func (e *LegacyLogEmitterContract) EmitLogIntsFromKey(_ []int, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") -} -func (e *LegacyLogEmitterContract) EmitLogIntsIndexedFromKey(_ []int, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") +func DeployLogEmitterContract(l zerolog.Logger, client *seth.Client) (LogEmitter, error) { + return DeployLogEmitterContractFromKey(l, client, 0) } -func (e *LegacyLogEmitterContract) EmitLogIntMultiIndexedFromKey(_ int, _ int, _ int, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") -} -func (e *LegacyLogEmitterContract) EmitLogStringsFromKey(_ []string, _ int) (*types.Transaction, error) { - panic("only Seth-based contracts support this method") + +func DeployLogEmitterContractFromKey(l zerolog.Logger, client *seth.Client, keyNum int) (LogEmitter, error) { + abi, err := le.LogEmitterMetaData.GetAbi() + if err != nil { + return &LogEmitterContract{}, fmt.Errorf("failed to get LogEmitter ABI: %w", err) + } + data, err := client.DeployContract(client.NewTXKeyOpts(keyNum), "LogEmitter", *abi, common.FromHex(le.LogEmitterMetaData.Bin)) + if err != nil { + return &LogEmitterContract{}, fmt.Errorf("LogEmitter instance deployment have failed: %w", err) + } + + instance, err := le.NewLogEmitter(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &LogEmitterContract{}, fmt.Errorf("failed to instantiate LogEmitter instance: %w", err) + } + + return &LogEmitterContract{ + client: client, + instance: instance, + address: data.Address, + l: l, + }, err } diff --git a/integration-tests/contracts/test_contracts_seth.go b/integration-tests/contracts/test_contracts_seth.go deleted file mode 100644 index 85e76054c7..0000000000 --- a/integration-tests/contracts/test_contracts_seth.go +++ /dev/null @@ -1,123 +0,0 @@ -package contracts - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" - - "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" -) - -type LogEmitterContract struct { - address common.Address - client *seth.Client - instance *le.LogEmitter - l zerolog.Logger -} - -func (e *LogEmitterContract) Address() common.Address { - return e.address -} - -func (e *LogEmitterContract) EmitLogIntsFromKey(ints []int, keyNum int) (*types.Transaction, error) { - bigInts := make([]*big.Int, len(ints)) - for i, v := range ints { - bigInts[i] = big.NewInt(int64(v)) - } - tx, err := e.client.Decode(e.instance.EmitLog1(e.client.NewTXKeyOpts(keyNum), bigInts)) - if err != nil { - return nil, err - } - - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogInts(ints []int) (*types.Transaction, error) { - return e.EmitLogIntsFromKey(ints, 0) -} - -func (e *LogEmitterContract) EmitLogIntsIndexedFromKey(ints []int, keyNum int) (*types.Transaction, error) { - bigInts := make([]*big.Int, len(ints)) - for i, v := range ints { - bigInts[i] = big.NewInt(int64(v)) - } - tx, err := e.client.Decode(e.instance.EmitLog2(e.client.NewTXKeyOpts(keyNum), bigInts)) - if err != nil { - return nil, err - } - - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogIntsIndexed(ints []int) (*types.Transaction, error) { - return e.EmitLogIntsIndexedFromKey(ints, 0) -} - -func (e *LogEmitterContract) EmitLogIntMultiIndexedFromKey(ints int, ints2 int, count int, keyNum int) (*types.Transaction, error) { - tx, err := e.client.Decode(e.instance.EmitLog4(e.client.NewTXKeyOpts(keyNum), big.NewInt(int64(ints)), big.NewInt(int64(ints2)), big.NewInt(int64(count)))) - if err != nil { - return nil, err - } - - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogIntMultiIndexed(ints int, ints2 int, count int) (*types.Transaction, error) { - return e.EmitLogIntMultiIndexedFromKey(ints, ints2, count, 0) -} - -func (e *LogEmitterContract) EmitLogStringsFromKey(strings []string, keyNum int) (*types.Transaction, error) { - tx, err := e.client.Decode(e.instance.EmitLog3(e.client.NewTXKeyOpts(keyNum), strings)) - if err != nil { - return nil, err - } - return tx.Transaction, nil -} - -func (e *LogEmitterContract) EmitLogStrings(strings []string) (*types.Transaction, error) { - return e.EmitLogStringsFromKey(strings, 0) -} - -func (e *LogEmitterContract) EmitLogInt(payload int) (*types.Transaction, error) { - return e.EmitLogInts([]int{payload}) -} - -func (e *LogEmitterContract) EmitLogIntIndexed(payload int) (*types.Transaction, error) { - return e.EmitLogIntsIndexed([]int{payload}) -} - -func (e *LogEmitterContract) EmitLogString(strings string) (*types.Transaction, error) { - return e.EmitLogStrings([]string{strings}) -} - -func DeployLogEmitterContract(l zerolog.Logger, client *seth.Client) (LogEmitter, error) { - return DeployLogEmitterContractFromKey(l, client, 0) -} - -func DeployLogEmitterContractFromKey(l zerolog.Logger, client *seth.Client, keyNum int) (LogEmitter, error) { - abi, err := le.LogEmitterMetaData.GetAbi() - if err != nil { - return &LogEmitterContract{}, fmt.Errorf("failed to get LogEmitter ABI: %w", err) - } - data, err := client.DeployContract(client.NewTXKeyOpts(keyNum), "LogEmitter", *abi, common.FromHex(le.LogEmitterMetaData.Bin)) - if err != nil { - return &LogEmitterContract{}, fmt.Errorf("LogEmitter instance deployment have failed: %w", err) - } - - instance, err := le.NewLogEmitter(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) - if err != nil { - return &LogEmitterContract{}, fmt.Errorf("failed to instantiate LogEmitter instance: %w", err) - } - - return &LogEmitterContract{ - client: client, - instance: instance, - address: data.Address, - l: l, - }, err -} diff --git a/integration-tests/docker/node_coverage_helper.go b/integration-tests/docker/node_coverage_helper.go index 52531bd35c..c24804b461 100644 --- a/integration-tests/docker/node_coverage_helper.go +++ b/integration-tests/docker/node_coverage_helper.go @@ -136,7 +136,7 @@ func (c *NodeCoverageHelper) copyCoverageFromNodes(ctx context.Context) error { errorsChan <- fmt.Errorf("failed to copy folder from container for node %d: %w", id, err) return } - finalDestPath = filepath.Join(finalDestPath, "go-coverage") // Assuming path structure /var/tmp/go-coverage/TestName/node_X/go-coverage + finalDestPath = filepath.Join(finalDestPath, "go-coverage") // Assuming path structure /var/tmp/go-coverage/TestRegex/node_X/go-coverage c.NodeCoverageDirs = append(c.NodeCoverageDirs, finalDestPath) }(node, i) } diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 8bb83cc8ee..1de16c9c6c 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "maps" - "math/big" "net/url" "os" "regexp" @@ -13,7 +12,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/pelletier/go-toml/v2" @@ -23,7 +21,6 @@ import ( tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/docker" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" @@ -96,12 +93,6 @@ func WithDbContainerName(name string) ClNodeOption { } } -func WithLogStream(ls *logstream.LogStream) ClNodeOption { - return func(c *ClNode) { - c.LogStream = ls - } -} - func WithImage(image string) ClNodeOption { return func(c *ClNode) { c.ContainerImage = image @@ -124,10 +115,11 @@ func WithPgDBOptions(opts ...test_env.PostgresDbOption) ClNodeOption { } } -func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, opts ...ClNodeOption) (*ClNode, error) { +func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, logStream *logstream.LogStream, opts ...ClNodeOption) (*ClNode, error) { nodeDefaultCName := fmt.Sprintf("%s-%s", "cl-node", uuid.NewString()[0:8]) pgDefaultCName := fmt.Sprintf("pg-%s", nodeDefaultCName) - pgDb, err := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName)) + + pgDb, err := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName), test_env.WithPostgresDbLogStream(logStream)) if err != nil { return nil, err } @@ -137,6 +129,7 @@ func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *ch ContainerImage: imageName, ContainerVersion: imageVersion, Networks: networks, + LogStream: logStream, }, UserEmail: "local@local.com", UserPassword: "localdevpassword", @@ -275,25 +268,6 @@ func (n *ClNode) ChainlinkNodeAddress() (common.Address, error) { return common.HexToAddress(addr), nil } -func (n *ClNode) Fund(evmClient blockchain.EVMClient, amount *big.Float) error { - toAddress, err := n.API.PrimaryEthAddress() - if err != nil { - return err - } - n.l.Debug(). - Str("ChainId", evmClient.GetChainID().String()). - Str("Address", toAddress). - Msg("Funding Chainlink Node") - toAddr := common.HexToAddress(toAddress) - gasEstimates, err := evmClient.EstimateGas(ethereum.CallMsg{ - To: &toAddr, - }) - if err != nil { - return err - } - return evmClient.Fund(toAddress, amount, gasEstimates) -} - func (n *ClNode) containerStartOrRestart(restartDb bool) error { var err error if restartDb { @@ -403,17 +377,25 @@ func (n *ClNode) ExecGetVersion() (string, error) { return "", errors.Errorf("could not find chainlink version in command output '%'", output) } +func (n ClNode) GetNodeConfigStr() (string, error) { + data, err := toml.Marshal(n.NodeConfig) + if err != nil { + return "", err + } + return string(data), nil +} + func (n *ClNode) getContainerRequest(secrets string) ( *tc.ContainerRequest, error) { configFile, err := os.CreateTemp("", "node_config") if err != nil { return nil, err } - data, err := toml.Marshal(n.NodeConfig) + configStr, err := n.GetNodeConfigStr() if err != nil { return nil, err } - _, err = configFile.WriteString(string(data)) + _, err = configFile.WriteString(configStr) if err != nil { return nil, err } diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index 12be7e182d..4a7964ddd2 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -2,19 +2,15 @@ package test_env import ( "context" - "encoding/json" "fmt" - "math/big" "os" "path/filepath" "runtime" "strings" "testing" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" tc "github.com/testcontainers/testcontainers-go" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" @@ -23,14 +19,10 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/runid" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" d "github.com/smartcontractkit/chainlink/integration-tests/docker" ) @@ -47,10 +39,6 @@ type CLClusterTestEnv struct { /* components */ ClCluster *ClCluster MockAdapter *test_env.Killgrave - evmClients map[int64]blockchain.EVMClient - sethClients map[int64]*seth.Client - ContractDeployer contracts.ContractDeployer - ContractLoader contracts.ContractLoader PrivateEthereumConfigs []*ctf_config.EthereumNetworkConfig EVMNetworks []*blockchain.EVMNetwork rpcProviders map[int64]*test_env.RpcProvider @@ -91,12 +79,6 @@ func (te *CLClusterTestEnv) WithTestInstance(t *testing.T) *CLClusterTestEnv { return te } -func (te *CLClusterTestEnv) ParallelTransactions(enabled bool) { - for _, evmClient := range te.evmClients { - evmClient.ParallelTransactions(enabled) - } -} - func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *ctf_config.EthereumNetworkConfig) (blockchain.EVMNetwork, test_env.RpcProvider, error) { // if environment is being restored from a previous state, use the existing config // this might fail terribly if temporary folders with chain data on the host machine were removed @@ -132,7 +114,6 @@ func (te *CLClusterTestEnv) StartMockAdapter() error { return te.MockAdapter.StartContainer() } -// pass config here func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig ctf_config.GlobalTestConfig, opts ...ClNodeOption) error { if te.Cfg != nil && te.Cfg.ClCluster != nil { te.ClCluster = te.Cfg.ClCluster @@ -145,10 +126,10 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i }, }, opts...) } - opts = append(opts, WithSecrets(secretsConfig), WithLogStream(te.LogStream)) + opts = append(opts, WithSecrets(secretsConfig)) te.ClCluster = &ClCluster{} for i := 0; i < count; i++ { - ocrNode, err := NewClNode([]string{te.DockerNetwork.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, opts...) + ocrNode, err := NewClNode([]string{te.DockerNetwork.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, te.LogStream, opts...) if err != nil { return err } @@ -167,41 +148,6 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i return te.ClCluster.Start() } -// FundChainlinkNodes will fund all the provided Chainlink nodes with a set amount of native currency -func (te *CLClusterTestEnv) FundChainlinkNodes(amount *big.Float) error { - if len(te.sethClients) == 0 && len(te.evmClients) == 0 { - return fmt.Errorf("both EVMClients and SethClient are nil, unable to fund chainlink nodes") - } - - if len(te.sethClients) > 0 && len(te.evmClients) > 0 { - return fmt.Errorf("both EVMClients and SethClient are set, you can't use both at the same time") - } - - if len(te.sethClients) > 0 { - for _, sethClient := range te.sethClients { - if err := actions_seth.FundChainlinkNodesFromRootAddress(te.l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(te.ClCluster.NodeAPIs()), amount); err != nil { - return err - } - } - } - - if len(te.evmClients) > 0 { - for _, evmClient := range te.evmClients { - for _, cl := range te.ClCluster.Nodes { - if err := cl.Fund(evmClient, amount); err != nil { - return fmt.Errorf("%s, err: %w", ErrFundCLNode, err) - } - } - err := evmClient.WaitForEvents() - if err != nil { - return err - } - } - } - - return nil -} - func (te *CLClusterTestEnv) Terminate() error { // TESTCONTAINERS_RYUK_DISABLED=false by default so ryuk will remove all // the containers and the Network @@ -231,32 +177,11 @@ func (te *CLClusterTestEnv) Cleanup(opts CleanupOpts) error { te.logWhetherAllContainersAreRunning() - if len(te.evmClients) == 0 && len(te.sethClients) == 0 { - return fmt.Errorf("both EVMClients and SethClient are nil, unable to return funds from chainlink nodes during cleanup") - } else if te.isSimulatedNetwork { - te.l.Info(). - Msg("Network is a simulated network. Skipping fund return.") - } else { - if err := te.returnFunds(); err != nil { - return err - } - } - err := te.handleNodeCoverageReports(opts.TestName) if err != nil { te.l.Error().Err(err).Msg("Error handling node coverage reports") } - // close EVMClient connections - for _, evmClient := range te.evmClients { - err := evmClient.Close() - return err - } - - for _, sethClient := range te.sethClients { - sethClient.Client.Close() - } - return nil } @@ -359,85 +284,28 @@ func (te *CLClusterTestEnv) logWhetherAllContainersAreRunning() { } } -func (te *CLClusterTestEnv) returnFunds() error { - te.l.Info().Msg("Attempting to return Chainlink node funds to default network wallets") - - if len(te.evmClients) == 0 && len(te.sethClients) == 0 { - return fmt.Errorf("both EVMClients and SethClient are nil, unable to return funds from chainlink nodes") - } - - for _, evmClient := range te.evmClients { - for _, chainlinkNode := range te.ClCluster.Nodes { - fundedKeys, err := chainlinkNode.API.ExportEVMKeysForChain(evmClient.GetChainID().String()) - if err != nil { - return err - } - for _, key := range fundedKeys { - keyToDecrypt, err := json.Marshal(key) - if err != nil { - return err - } - // This can take up a good bit of RAM and time. When running on the remote-test-runner, this can lead to OOM - // issues. So we avoid running in parallel; slower, but safer. - decryptedKey, err := keystore.DecryptKey(keyToDecrypt, client.ChainlinkKeyPassword) - if err != nil { - return err - } - if te.evmClients[0] != nil { - te.l.Debug(). - Str("ChainId", evmClient.GetChainID().String()). - Msg("Returning funds from chainlink node") - if err = evmClient.ReturnFunds(decryptedKey.PrivateKey); err != nil { - // If we fail to return funds from one, go on to try the others anyway - te.l.Error().Err(err).Str("Node", chainlinkNode.ContainerName).Msg("Error returning funds from node") - } - } - } - } - } - - for _, sethClient := range te.sethClients { - if err := actions_seth.ReturnFundsFromNodes(te.l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(te.ClCluster.NodeAPIs())); err != nil { - te.l.Error().Err(err).Msg("Error returning funds from node") - } - } - - te.l.Info().Msg("Returned funds from Chainlink nodes") - return nil -} - -func (te *CLClusterTestEnv) GetEVMClient(chainId int64) (blockchain.EVMClient, error) { - if len(te.sethClients) > 0 { - return nil, fmt.Errorf("Environment is using Seth clients, not EVM clients") - } - - if evmClient, ok := te.evmClients[chainId]; ok { - return evmClient, nil +func (te *CLClusterTestEnv) GetRpcProvider(chainId int64) (*test_env.RpcProvider, error) { + if rpc, ok := te.rpcProviders[chainId]; ok { + return rpc, nil } - return nil, fmt.Errorf("no EVMClient available for chain ID %d", chainId) + return nil, fmt.Errorf("no RPC provider available for chain ID %d", chainId) } -func (te *CLClusterTestEnv) GetSethClient(chainId int64) (*seth.Client, error) { - if len(te.evmClients) > 0 { - return nil, fmt.Errorf("Environment is using EVMClients, not Seth clients") - } - if sethClient, ok := te.sethClients[chainId]; ok { - return sethClient, nil +func (te *CLClusterTestEnv) GetFirstEvmNetwork() (*blockchain.EVMNetwork, error) { + if len(te.EVMNetworks) == 0 { + return nil, fmt.Errorf("no EVM networks available") } - return nil, fmt.Errorf("no Seth client available for chain ID %d", chainId) + return te.EVMNetworks[0], nil } -func (te *CLClusterTestEnv) GetSethClientForSelectedNetwork() (*seth.Client, error) { - n := networks.MustGetSelectedNetworkConfig(te.TestConfig.GetNetworkConfig())[0] - return te.GetSethClient(n.ChainID) -} - -func (te *CLClusterTestEnv) GetRpcProvider(chainId int64) (*test_env.RpcProvider, error) { - if rpc, ok := te.rpcProviders[chainId]; ok { - return rpc, nil +func (te *CLClusterTestEnv) GetEVMNetworkForChainId(chainId int64) (*blockchain.EVMNetwork, error) { + for _, network := range te.EVMNetworks { + if network.ChainID == chainId { + return network, nil + } } - return nil, fmt.Errorf("no RPC provider available for chain ID %d", chainId) + return nil, fmt.Errorf("no EVM network available for chain ID %d", chainId) } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 5bd746bded..ea7a87fbcd 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -2,17 +2,14 @@ package test_env import ( "fmt" - "math/big" "os" "slices" "strings" "testing" - "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" @@ -25,8 +22,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" ) @@ -47,8 +42,6 @@ type ChainlinkNodeLogScannerSettings struct { type CLTestEnvBuilder struct { hasLogStream bool hasKillgrave bool - hasSeth bool - hasEVMClient bool clNodeConfig *chainlink.Config secretsConfig string clNodesCount int @@ -65,9 +58,6 @@ type CLTestEnvBuilder struct { privateEthereumNetworks []*ctf_config.EthereumNetworkConfig testConfig ctf_config.GlobalTestConfig chainlinkNodeLogScannerSettings *ChainlinkNodeLogScannerSettings - - /* funding */ - ETHFunds *big.Float } var DefaultAllowedMessages = []testreporters.AllowedLogMessage{ @@ -94,7 +84,6 @@ func NewCLTestEnvBuilder() *CLTestEnvBuilder { return &CLTestEnvBuilder{ l: log.Logger, hasLogStream: true, - hasEVMClient: true, isEVM: true, chainlinkNodeLogScannerSettings: &DefaultChainlinkNodeLogScannerSettings, } @@ -169,23 +158,6 @@ func (b *CLTestEnvBuilder) WithCLNodeOptions(opt ...ClNodeOption) *CLTestEnvBuil return b } -func (b *CLTestEnvBuilder) WithFunding(eth *big.Float) *CLTestEnvBuilder { - b.ETHFunds = eth - return b -} - -func (b *CLTestEnvBuilder) WithSeth() *CLTestEnvBuilder { - b.hasSeth = true - b.hasEVMClient = false - return b -} - -func (b *CLTestEnvBuilder) WithoutEvmClients() *CLTestEnvBuilder { - b.hasSeth = false - b.hasEVMClient = false - return b -} - func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en ctf_config.EthereumNetworkConfig) *CLTestEnvBuilder { b.privateEthereumNetworks = append(b.privateEthereumNetworks, &en) return b @@ -380,7 +352,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if len(b.privateEthereumNetworks) > 1 { b.te.rpcProviders = make(map[int64]*test_env.RpcProvider) b.te.EVMNetworks = make([]*blockchain.EVMNetwork, 0) - b.te.evmClients = make(map[int64]blockchain.EVMClient) for _, en := range b.privateEthereumNetworks { en.DockerNetworkNames = []string{b.te.DockerNetwork.Name} networkConfig, rpcProvider, err := b.te.StartEthereumNetwork(en) @@ -388,23 +359,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return nil, err } - if b.hasEVMClient { - evmClient, err := blockchain.NewEVMClientFromNetwork(networkConfig, b.l) - if err != nil { - return nil, err - } - b.te.evmClients[networkConfig.ChainID] = evmClient - } - - if b.hasSeth { - sethClient, err := actions_seth.GetChainClient(b.testConfig, networkConfig) - if err != nil { - return nil, err - } - - b.te.sethClients[networkConfig.ChainID] = sethClient - } - b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) } @@ -442,6 +396,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { // That is, when we specify we want to run on a live network in our config, we will run on the live network and not bother with a private network. // Even if we explicitly declare that we want to run on a private network in the test. // Keeping this a Kludge for now as SETH transition should change all of this anyway. + b.te.EVMNetworks = make([]*blockchain.EVMNetwork, 0) if len(b.privateEthereumNetworks) == 1 { if networkConfig.Simulated { // TODO here we should save the ethereum network config to te.Cfg, but it doesn't exist at this point @@ -466,17 +421,16 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider b.te.isSimulatedNetwork = false } - b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) - - } - - if !b.hasSeth && !b.hasEVMClient { - log.Debug().Msg("No EVM client or SETH client specified, not starting any clients") - } - - if b.hasSeth && b.hasEVMClient { - return nil, errors.New("you can't use both Seth and EMVClient at the same time") + } else if len(b.privateEthereumNetworks) == 0 && !networkConfig.Simulated { + b.te.l.Warn(). + Str("Network", networkConfig.Name). + Int64("Chain ID", networkConfig.ChainID). + Msg("Private network config provided, but we are running on a live network. Ignoring private network config.") + rpcProvider := test_env.NewRPCProvider(networkConfig.HTTPURLs, networkConfig.URLs, networkConfig.HTTPURLs, networkConfig.URLs) + b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider + b.te.isSimulatedNetwork = false } + b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) if b.isEVM { if b.evmNetworkOption != nil && len(b.evmNetworkOption) > 0 { @@ -484,37 +438,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { fn(&networkConfig) } } - if b.hasEVMClient { - bc, err := blockchain.NewEVMClientFromNetwork(networkConfig, b.l) - if err != nil { - return nil, err - } - - b.te.evmClients = make(map[int64]blockchain.EVMClient) - b.te.evmClients[networkConfig.ChainID] = bc - - cd, err := contracts.NewContractDeployer(bc, b.l) - if err != nil { - return nil, err - } - b.te.ContractDeployer = cd - - cl, err := contracts.NewContractLoader(bc, b.l) - if err != nil { - return nil, err - } - b.te.ContractLoader = cl - } - - if b.hasSeth { - b.te.sethClients = make(map[int64]*seth.Client) - sethClient, err := actions_seth.GetChainClient(b.testConfig, networkConfig) - if err != nil { - return nil, err - } - - b.te.sethClients[networkConfig.ChainID] = sethClient - } } var nodeCsaKeys []string @@ -564,23 +487,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.defaultNodeCsaKeys = nodeCsaKeys } - if b.clNodesCount > 0 && b.ETHFunds != nil { - if b.hasEVMClient { - b.te.ParallelTransactions(true) - defer b.te.ParallelTransactions(false) - if err := b.te.FundChainlinkNodes(b.ETHFunds); err != nil { - return nil, err - } - } - if b.hasSeth { - for _, sethClient := range b.te.sethClients { - if err := actions_seth.FundChainlinkNodesFromRootAddress(b.l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(b.te.ClCluster.NodeAPIs()), b.ETHFunds); err != nil { - return nil, err - } - } - } - } - var enDesc string if len(b.te.PrivateEthereumConfigs) > 0 { for _, en := range b.te.PrivateEthereumConfigs { diff --git a/integration-tests/experiments/gas_test.go b/integration-tests/experiments/gas_test.go index a2dbf624c8..88bfbcf192 100644 --- a/integration-tests/experiments/gas_test.go +++ b/integration-tests/experiments/gas_test.go @@ -5,12 +5,13 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" - - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) @@ -21,10 +22,10 @@ func TestGasExperiment(t *testing.T) { require.NoError(t, err, "Error getting config") network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - seth, err := actions_seth.GetChainClient(&config, network) + seth, err := seth_utils.GetChainClient(&config, network) require.NoError(t, err, "Error creating seth client") - _, err = actions_seth.SendFunds(l, seth, actions_seth.FundsToSendPayload{ + _, err = actions.SendFunds(l, seth, actions.FundsToSendPayload{ ToAddress: seth.Addresses[0], Amount: big.NewInt(10_000_000), PrivateKey: seth.PrivateKeys[0], diff --git a/integration-tests/go.mod b/integration-tests/go.mod index a30b541a76..558331cf57 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -11,6 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 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/v1alpha1 v0.0.0-20220226050744-799408773657 github.com/cli/go-gh/v2 v2.0.0 github.com/ethereum/go-ethereum v1.13.8 github.com/fxamacker/cbor/v2 v2.5.0 @@ -25,20 +26,22 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 github.com/prometheus/common v0.45.0 - github.com/rs/zerolog v1.30.0 + github.com/rs/zerolog v1.31.0 github.com/scylladb/go-reflectx v1.0.1 github.com/segmentio/ksuid v1.0.4 github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chain-selectors v1.0.17 - github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce - github.com/smartcontractkit/chainlink-testing-framework v1.31.0 + github.com/smartcontractkit/chainlink-automation v1.0.4 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 + github.com/smartcontractkit/chainlink-testing-framework v1.31.4 + github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 + github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c - github.com/smartcontractkit/seth v1.0.11 + github.com/smartcontractkit/seth v1.0.12 github.com/smartcontractkit/wasp v0.4.7 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 @@ -54,13 +57,13 @@ require ( golang.org/x/sync v0.6.0 golang.org/x/text v0.14.0 gopkg.in/guregu/null.v4 v4.0.0 + k8s.io/apimachinery v0.28.2 ) // avoids ambigious imports of indirect dependencies exclude github.com/hashicorp/consul v1.2.1 replace ( - // Pin K8s versions as their updates are highly disruptive and go mod keeps wanting to update them k8s.io/api => k8s.io/api v0.25.11 k8s.io/client-go => k8s.io/client-go v0.25.11 k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d @@ -119,7 +122,6 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/chzyer/readline v1.5.1 // indirect @@ -386,7 +388,6 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 // indirect - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect @@ -470,7 +471,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.28.2 // indirect k8s.io/apiextensions-apiserver v0.25.3 // indirect - k8s.io/apimachinery v0.28.2 // indirect k8s.io/cli-runtime v0.25.11 // indirect k8s.io/client-go v0.28.2 // indirect k8s.io/component-base v0.26.2 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 32e1588142..029484192e 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1192,6 +1192,7 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1451,8 +1452,8 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -1506,10 +1507,10 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/chain-selectors v1.0.17 h1:otOlYUnutS8oQBEAi9RLQICqZP0Nxy0k8vOZuSMJa4w= github.com/smartcontractkit/chain-selectors v1.0.17/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= -github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= +github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 h1:6322qmPgHgYF/d/NjjbuZvF0Qfz4Hp+wLtLeS3SA3mI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= @@ -1520,20 +1521,22 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a/go.mod h1:QqcZSwLgEIn7YraAIRmomnBMAuVFephiHrIWVlkWbFI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 h1:h1E87+z+JcUEfvbJVF56SnZA/YUFE5ewUE61MaR/Ewg= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696/go.mod h1:OiWUTrrpSLLTMh7FINWjEh6mmDJCVPaC4yEsDCVaWdU= -github.com/smartcontractkit/chainlink-testing-framework v1.31.0 h1:7xge1hsbIhvqIZmvXiqiRlvLFrZ271Tzg3Scj68Ru7w= -github.com/smartcontractkit/chainlink-testing-framework v1.31.0/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= +github.com/smartcontractkit/chainlink-testing-framework v1.31.4 h1:5/zF5Z2w+/HTvUSSJNhWSiHvlQ2O2qxRw4e1fBbVraQ= +github.com/smartcontractkit/chainlink-testing-framework v1.31.4/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= +github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= +github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.0.11 h1:Ct8wSifW2ZXnyHtYRKaawBnpW7Ef0m8zItUcqYPallM= -github.com/smartcontractkit/seth v1.0.11/go.mod h1:fVCE+8LD6AbU7d8BHZ1uS/ceJ+8JO0iVTUcDdQmGPAc= +github.com/smartcontractkit/seth v1.0.12 h1:iVdgMx42XWanPPnBaM5StR4c1XsTr/0/B/kKRZL5BsY= +github.com/smartcontractkit/seth v1.0.12/go.mod h1:thWtbLyW4nRHJGzC5heknQDORoJPErE15sF34LHkorg= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 7f066aa8bc..1761e58f86 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -40,8 +40,8 @@ import ( gowiremock "github.com/wiremock/go-wiremock" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" contractseth "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -319,8 +319,7 @@ Load Config: require.NoError(t, err, "Error running chainlink DON") testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - - chainClient, err := actions_seth.GetChainClientWithConfigFunction(loadedTestConfig, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(loadedTestConfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -393,7 +392,7 @@ Load Config: a.SetupAutomationDeployment(t) - err = actions_seth.FundChainlinkNodesFromRootAddress(l, a.ChainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes[1:]), big.NewFloat(*loadedTestConfig.Common.ChainlinkNodeFunding)) + err = actions.FundChainlinkNodesFromRootAddress(l, a.ChainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes[1:]), big.NewFloat(*loadedTestConfig.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Error funding chainlink nodes") consumerContracts := make([]contracts.KeeperConsumer, 0) @@ -791,7 +790,7 @@ Test Duration: %s` } t.Cleanup(func() { - if err = actions_seth.TeardownRemoteSuite(t, chainClient, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &loadedTestConfig); err != nil { + if err = actions.TeardownRemoteSuite(t, chainClient, testEnvironment.Cfg.Namespace, chainlinkNodes, nil, &loadedTestConfig); err != nil { l.Error().Err(err).Msg("Error when tearing down remote suite") testEnvironment.Cfg.TTL += time.Hour * 48 err := testEnvironment.Run() diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index 4fa13149d7..30559743e1 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -12,7 +12,7 @@ import ( ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" aconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" @@ -97,7 +97,7 @@ type task struct { func deployConsumerAndTriggerContracts(l zerolog.Logger, loadConfig aconfig.Load, chainClient *seth.Client, multicallAddress common.Address, maxConcurrency int, automationDefaultLinkFunds *big.Int, linkToken contracts.LinkToken) (DeploymentData, error) { data := DeploymentData{} - concurrency, err := actions_seth.GetAndAssertCorrectConcurrency(chainClient, 1) + concurrency, err := actions.GetAndAssertCorrectConcurrency(chainClient, 1) if err != nil { return DeploymentData{}, err } @@ -197,7 +197,7 @@ func deployConsumerAndTriggerContracts(l zerolog.Logger, loadConfig aconfig.Load } } - sendErr := actions_seth.SendLinkFundsToDeploymentAddresses(chainClient, concurrency, *loadConfig.NumberOfUpkeeps, *loadConfig.NumberOfUpkeeps/concurrency, multicallAddress, automationDefaultLinkFunds, linkToken) + sendErr := actions.SendLinkFundsToDeploymentAddresses(chainClient, concurrency, *loadConfig.NumberOfUpkeeps, *loadConfig.NumberOfUpkeeps/concurrency, multicallAddress, automationDefaultLinkFunds, linkToken) if sendErr != nil { return DeploymentData{}, sendErr } diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index e6f96ccbdf..bf1cc54f00 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -8,6 +8,8 @@ import ( "strconv" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/crypto" "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" @@ -19,7 +21,6 @@ import ( ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/networks" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types" ) @@ -53,7 +54,7 @@ type S4SecretsCfg struct { func SetupLocalLoadTestEnv(globalConfig ctf_config.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { selectedNetwork := networks.MustGetSelectedNetworkConfig(globalConfig.GetNetworkConfig())[0] - seth, err := actions_seth.GetChainClient(globalConfig, selectedNetwork) + seth, err := seth_utils.GetChainClient(globalConfig, selectedNetwork) if err != nil { return nil, err } diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 4182221c63..2d3324f399 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -13,15 +13,15 @@ require ( github.com/go-resty/resty/v2 v2.11.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 - github.com/rs/zerolog v1.30.0 + github.com/rs/zerolog v1.31.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce - github.com/smartcontractkit/chainlink-testing-framework v1.31.0 + github.com/smartcontractkit/chainlink-automation v1.0.4 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 + github.com/smartcontractkit/chainlink-testing-framework v1.31.4 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c - github.com/smartcontractkit/seth v1.0.11 + github.com/smartcontractkit/seth v1.0.12 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.7 github.com/stretchr/testify v1.9.0 @@ -370,7 +370,7 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240522213638-159fb2d99917 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 // indirect - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 // indirect + github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect @@ -492,7 +492,7 @@ replace ( github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 // until merged upstream: https://github.com/hashicorp/go-plugin/pull/257 - github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 + github.com/hashicorp/go-plugin => github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d7f5d53450..af2cc23802 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1186,6 +1186,7 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1441,8 +1442,8 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -1496,10 +1497,10 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/chain-selectors v1.0.17 h1:otOlYUnutS8oQBEAi9RLQICqZP0Nxy0k8vOZuSMJa4w= github.com/smartcontractkit/chain-selectors v1.0.17/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= -github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= -github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce h1:/CjY8L4lVJh9E8NKg3bdAgsxj+zKg9XYtXR71ZWWMXo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240607135320-c9bc0a2ac0ce/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= +github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= +github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985 h1:6322qmPgHgYF/d/NjjbuZvF0Qfz4Hp+wLtLeS3SA3mI= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240624150733-1eff5dedc985/go.mod h1:L32xvCpk84Nglit64OhySPMP1tM3TTBK7Tw0qZl7Sd4= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d h1:5tgMC5Gi2UAOKZ+m28W8ubjLeR0pQCAcrz6eQ0rW510= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240524214833-c362c2ebbd2d/go.mod h1:0UNuO3nDt9MFsZPaHJBEUolxVkN0iC69j1ccDp95e8k= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= @@ -1510,20 +1511,20 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240605170242-555ff582f36a/go.mod h1:QqcZSwLgEIn7YraAIRmomnBMAuVFephiHrIWVlkWbFI= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696 h1:h1E87+z+JcUEfvbJVF56SnZA/YUFE5ewUE61MaR/Ewg= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240531021326-99118e47f696/go.mod h1:OiWUTrrpSLLTMh7FINWjEh6mmDJCVPaC4yEsDCVaWdU= -github.com/smartcontractkit/chainlink-testing-framework v1.31.0 h1:7xge1hsbIhvqIZmvXiqiRlvLFrZ271Tzg3Scj68Ru7w= -github.com/smartcontractkit/chainlink-testing-framework v1.31.0/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449 h1:fX/xmGm1GBsD1ZZnooNT+eWA0hiTAqFlHzOC5CY4dy8= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240328204215-ac91f55f1449/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= +github.com/smartcontractkit/chainlink-testing-framework v1.31.4 h1:5/zF5Z2w+/HTvUSSJNhWSiHvlQ2O2qxRw4e1fBbVraQ= +github.com/smartcontractkit/chainlink-testing-framework v1.31.4/go.mod h1:E6uNEZhZZid9PHv6/Kq5Vn63GlO61ZcKB+/f0DKo3Q4= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= -github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88+ZznniNJZbZPWAvHQU8SwKAdHngdDZ+pvVgB5ss= -github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= +github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= +github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.0.11 h1:Ct8wSifW2ZXnyHtYRKaawBnpW7Ef0m8zItUcqYPallM= -github.com/smartcontractkit/seth v1.0.11/go.mod h1:fVCE+8LD6AbU7d8BHZ1uS/ceJ+8JO0iVTUcDdQmGPAc= +github.com/smartcontractkit/seth v1.0.12 h1:iVdgMx42XWanPPnBaM5StR4c1XsTr/0/B/kKRZL5BsY= +github.com/smartcontractkit/seth v1.0.12/go.mod h1:thWtbLyW4nRHJGzC5heknQDORoJPErE15sF34LHkorg= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/ocr/helper.go b/integration-tests/load/ocr/helper.go index ad07ccd4fd..f95bf143bc 100644 --- a/integration-tests/load/ocr/helper.go +++ b/integration-tests/load/ocr/helper.go @@ -13,7 +13,6 @@ import ( client2 "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) @@ -23,7 +22,7 @@ func SetupCluster( seth *seth.Client, workerNodes []*client.ChainlinkK8sClient, ) (common.Address, error) { - err := actions_seth.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(3)) + err := actions.FundChainlinkNodesFromRootAddress(l, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(3)) if err != nil { return common.Address{}, err } @@ -42,7 +41,7 @@ func SetupFeed( bootstrapNode *client.ChainlinkK8sClient, workerNodes []*client.ChainlinkK8sClient, ) ([]contracts.OffchainAggregator, error) { - ocrInstances, err := actions_seth.DeployOCRv1Contracts(l, seth, 1, lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(l, seth, 1, lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(workerNodes)) if err != nil { return nil, err } diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index e836fda39c..15f52acbff 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -3,13 +3,14 @@ package ocr import ( "testing" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/wasp" "github.com/smartcontractkit/chainlink-testing-framework/logging" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/k8s" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) @@ -30,7 +31,7 @@ func TestOCRLoad(t *testing.T) { evmNetwork, msClient, bootstrapNode, workerNodes, err := k8s.ConnectRemote() require.NoError(t, err) - seth, err := actions_seth.GetChainClient(config, *evmNetwork) + seth, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error creating seth client") lta, err := SetupCluster(l, seth, workerNodes) @@ -66,7 +67,7 @@ func TestOCRVolume(t *testing.T) { evmNetwork, msClient, bootstrapNode, workerNodes, err := k8s.ConnectRemote() require.NoError(t, err) - seth, err := actions_seth.GetChainClient(config, *evmNetwork) + seth, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error creating seth client") lta, err := SetupCluster(l, seth, workerNodes) diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index 83f43a94e4..88f186c5ee 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -17,7 +17,6 @@ import ( client2 "github.com/smartcontractkit/chainlink-testing-framework/client" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) @@ -79,7 +78,7 @@ func (m *VU) Clone(_ *wasp.Generator) wasp.VirtualUser { } func (m *VU) Setup(_ *wasp.Generator) error { - ocrInstances, err := actions_seth.DeployOCRv1Contracts(m.l, m.seth, 1, m.lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(m.workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(m.l, m.seth, 1, m.lta, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(m.workerNodes)) if err != nil { return err } diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 365826002c..d5612e885e 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" @@ -16,7 +18,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -39,6 +40,7 @@ func TestVRFV2Performance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() @@ -58,9 +60,6 @@ func TestVRFV2Performance(t *testing.T) { } network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") - updatedLabels := UpdateLabels(labels, t) l.Info(). @@ -74,7 +73,6 @@ func TestVRFV2Performance(t *testing.T) { Msg("Performance Test Configuration") cleanupFn := func() { teardown(t, vrfContracts.VRFV2Consumers[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { @@ -105,13 +103,12 @@ func TestVRFV2Performance(t *testing.T) { UseTestCoordinator: true, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2 universe") var consumers []contracts.VRFv2LoadTestConsumer subIDs, consumers, err := vrfv2.SetupSubsAndConsumersForExistingEnv( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, vrfContracts.LinkToken, 1, @@ -184,6 +181,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -215,11 +213,9 @@ func TestVRFV2BHSPerformance(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") + cleanupFn := func() { teardown(t, vrfContracts.VRFV2Consumers[0], lc, updatedLabels, testReporter, testType, &testConfig) - if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -248,16 +244,16 @@ func TestVRFV2BHSPerformance(t *testing.T) { UseTestCoordinator: true, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2 universe") t.Run("vrfv2 and bhs performance test", func(t *testing.T) { configCopy := testConfig.MustCopy().(tc.TestConfig) // Underfund Subscription configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) + underfundedSubIDs, consumers, err := vrfv2.SetupSubsAndConsumersForExistingEnv( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, vrfContracts.LinkToken, 1, diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 99edbdf8d5..9ab1e8d745 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" @@ -14,13 +16,11 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -38,6 +38,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() @@ -57,8 +58,6 @@ func TestVRFV2PlusPerformance(t *testing.T) { } network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") updatedLabels := UpdateLabels(labels, t) l.Info(). @@ -73,7 +72,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { cleanupFn := func() { teardown(t, vrfContracts.VRFV2PlusConsumer[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") + if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -100,14 +99,14 @@ func TestVRFV2PlusPerformance(t *testing.T) { NumberOfTxKeysToCreate: *vrfv2PlusConfig.General.NumberOfSendingKeysToCreate, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") var consumers []contracts.VRFv2PlusLoadTestConsumer + subIDs, consumers, err := vrfv2plus.SetupSubsAndConsumersForExistingEnv( testcontext.Get(t), - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, vrfContracts.LinkToken, 1, @@ -181,6 +180,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -212,12 +212,9 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] chainID := network.ChainID - sethClient, err := actions_seth.GetChainClient(testConfig, network) - require.NoError(t, err, "Error creating seth client") cleanupFn := func() { teardown(t, vrfContracts.VRFV2PlusConsumer[0], lc, updatedLabels, testReporter, testType, &testConfig) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -245,7 +242,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { NumberOfTxKeysToCreate: *vrfv2PlusConfig.General.NumberOfSendingKeysToCreate, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") t.Run("vrfv2plus and bhs performance test", func(t *testing.T) { @@ -256,8 +253,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { underfundedSubIDs, consumers, err := vrfv2plus.SetupSubsAndConsumersForExistingEnv( testcontext.Get(t), - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, vrfContracts.LinkToken, 1, @@ -310,8 +306,6 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { var wgBlockNumberTobe sync.WaitGroup wgBlockNumberTobe.Add(1) //Wait at least 256 blocks - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") latestBlockNumber, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "error getting latest block number") _, err = actions.WaitForBlockNumberToBe( diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index f89644eb81..4c7b275e29 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -33,7 +33,6 @@ func TestVersionUpgrade(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 659a7f2b2f..e41244e55e 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -7,11 +7,12 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/onsi/gomega" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" @@ -156,38 +157,42 @@ func TestAutomationReorg(t *testing.T) { if testEnvironment.WillUseRemoteRunner() { return } - gethURL := testEnvironment.URLs["Simulated Geth_http"][0] - require.NotEmpty(t, gethURL, "Geth URL should not be empty") - gethRPCClient := ctf_client.NewRPCClient(gethURL) + if !testEnvironment.Cfg.InsideK8s { + // Test is running locally, set forwarded URL of Geth blockchain node + wsURLs := testEnvironment.URLs[network.Name+"_internal"] + httpURLs := testEnvironment.URLs[network.Name+"_internal_http"] + require.NotEmpty(t, wsURLs, "Forwarded Geth URLs should not be empty") + require.NotEmpty(t, httpURLs, "Forwarded Geth URLs should not be empty") + network.URLs = wsURLs + network.HTTPURLs = httpURLs + } - chainClient, err := blockchain.NewEVMClient(network, testEnvironment, l) + gethRPCClient := ctf_client.NewRPCClient(network.HTTPURLs[0]) + chainClient, err := seth_utils.GetChainClient(config, network) require.NoError(t, err, "Error connecting to blockchain") - contractDeployer, err := contracts.NewContractDeployer(chainClient, l) - require.NoError(t, err, "Error building contract deployer") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) require.NoError(t, err, "Error connecting to Chainlink nodes") - chainClient.ParallelTransactions(true) // Register cleanup for any test t.Cleanup(func() { - err := actions.TeardownSuite(t, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config, chainClient) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.PanicLevel, &config) require.NoError(t, err, "Error tearing down environment") }) - err = actions.FundChainlinkNodes(chainlinkNodes, chainClient, nodeFundsAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), nodeFundsAmount) require.NoError(t, err, "Error funding Chainlink nodes") - linkToken, err := contractDeployer.DeployLinkTokenContract() + linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) require.NoError(t, err, "Error deploying LINK token") registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( t, + chainClient, registryVersion, defaultOCRRegistryConfig, linkToken, - contractDeployer, - chainClient, ) + // Fund the registry with LINK err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(upkeepCount)))) require.NoError(t, err, "Funding keeper registry contract shouldn't fail") @@ -203,11 +208,21 @@ func TestAutomationReorg(t *testing.T) { err = registry.SetConfigTypeSafe(ocrConfig) } require.NoError(t, err, "Registry config should be be set successfully") - require.NoError(t, chainClient.WaitForEvents(), "Waiting for config to be set") // Use the name to determine if this is a log trigger or not isLogTrigger := name == "registry_2_1_logtrigger" || name == "registry_2_2_logtrigger" - consumers, upkeepIDs := actions.DeployConsumers(t, registry, registrar, linkToken, contractDeployer, chainClient, upkeepCount, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, isLogTrigger, false) + consumers, upkeepIDs := actions.DeployConsumers( + t, + chainClient, + registry, + registrar, + linkToken, + upkeepCount, + big.NewInt(defaultLinkFunds), + defaultUpkeepGasLimit, + isLogTrigger, + false, + ) if isLogTrigger { for i := 0; i < len(upkeepIDs); i++ { diff --git a/integration-tests/reorg/reorg_confirmer.go b/integration-tests/reorg/reorg_confirmer.go deleted file mode 100644 index a5659e6678..0000000000 --- a/integration-tests/reorg/reorg_confirmer.go +++ /dev/null @@ -1,284 +0,0 @@ -package reorg - -import ( - "context" - "fmt" - "math/big" - "sync" - "sync/atomic" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog/log" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" -) - -// The steps are: -// 1. Await initial network consensus for N blocks -// 2. Fork the network, separate node 0 from 1 and 2 -// 3. Await alternative blocks mined on node zero, -// nodes 1 and 2 will have longer chain with more block difficulty so blocks of node 0 must be replaced -// 4. Await consensus for N blocks, check alt block hashes now -const ( - InitConsensus int64 = iota - NetworkFork - CheckBlocks - Consensus - Wait -) - -type ReorgConfig struct { - FromPodLabel string - ToPodLabel string - Network blockchain.EVMClient - Env *environment.Environment - BlockConsensusThreshold int - Timeout time.Duration -} - -// ReorgController reorg stats collecting struct -type ReorgController struct { - cfg *ReorgConfig - ReorgDepth int - numberOfNodes int - currentBlockConsensus int - forkBlockNumber int64 - currentAltBlocks int - currentVerifiedBlocks int - networkStep atomic.Int64 - altBlockNumbers []int64 - blocksByNode map[int]map[int64]blockchain.NodeHeader - blockHashes map[int64][]common.Hash - chaosExperimentName string - initConsensusReady chan struct{} - reorgStarted chan struct{} - depthReached chan struct{} - once sync.Once - mutex sync.Mutex - ctx context.Context - cancel context.CancelFunc - doneChan chan struct{} - complete bool -} - -// NewReorgController creates a type that can create reorg chaos and confirm reorg has happened -func NewReorgController(cfg *ReorgConfig) (*ReorgController, error) { - if len(cfg.Network.GetClients()) == 1 { - return nil, fmt.Errorf("need at least 3 nodes to re-org") - } - ctx, ctxCancel := context.WithTimeout(context.Background(), cfg.Timeout) - rc := &ReorgController{ - cfg: cfg, - numberOfNodes: len(cfg.Network.GetClients()), - doneChan: make(chan struct{}, 100), - altBlockNumbers: make([]int64, 0), - blockHashes: map[int64][]common.Hash{}, - blocksByNode: map[int]map[int64]blockchain.NodeHeader{}, - initConsensusReady: make(chan struct{}, 100), - reorgStarted: make(chan struct{}, 100), - depthReached: make(chan struct{}, 100), - ctx: ctx, - cancel: ctxCancel, - } - rc.networkStep.Store(InitConsensus) - for _, c := range cfg.Network.GetClients() { - c.AddHeaderEventSubscription("reorg", rc) - } - <-rc.initConsensusReady - return rc, nil -} - -// ReOrg start re-org -func (rc *ReorgController) ReOrg(depth int) { - rc.ReorgDepth = depth - rc.networkStep.Store(NetworkFork) -} - -// WaitDepthReached wait until N alternative blocks are mined -func (rc *ReorgController) WaitDepthReached() error { - <-rc.depthReached - rc.networkStep.Store(Consensus) - return rc.cfg.Network.WaitForEvents() -} - -// WaitReorgStarted waits until first alternative block is present -func (rc *ReorgController) WaitReorgStarted() { - <-rc.reorgStarted -} - -// ReceiveHeader receives header marked by node that mined it, -// forks the network and record all alternative block numbers on node 0 -func (rc *ReorgController) ReceiveHeader(header blockchain.NodeHeader) error { - rc.mutex.Lock() - defer rc.mutex.Unlock() - rc.appendBlockHeader(header) - switch rc.networkStep.Load() { - case Wait: - case InitConsensus: - if rc.hasNetworkFormedConsensus(header) { - rc.networkStep.Store(Wait) - rc.initConsensusReady <- struct{}{} - } - case NetworkFork: - if err := rc.forkNetwork(header); err != nil { - return err - } - case CheckBlocks: - if err := rc.compareBlocks(header); err != nil { - return err - } - case Consensus: - if rc.hasNetworkFormedConsensus(header) { - rc.complete = true - rc.cancel() - } - } - return nil -} - -func (rc *ReorgController) Complete() bool { - return rc.complete -} - -// VerifyReorgComplete verifies that all blocks are replaced by reorg -func (rc *ReorgController) VerifyReorgComplete() error { - // we are excluding the last block because we can't control joining while blocks were mined - for _, ab := range rc.altBlockNumbers[:len(rc.altBlockNumbers)-1] { - bb := rc.blocksByNode[0][ab] - h, err := rc.cfg.Network.HeaderHashByNumber(context.Background(), big.NewInt(ab)) - if err != nil { - return err - } - log.Info(). - Int64("Number", bb.Number.Int64()). - Str("Hash before", bb.Hash.String()). - Str("Hash after", h). - Msg("Comparing block") - if bb.Hash.String() != h { - rc.currentVerifiedBlocks++ - } - } - if rc.currentVerifiedBlocks+1 < rc.ReorgDepth { - return fmt.Errorf("Reorg depth has not met") - } - return nil -} - -func (rc *ReorgController) isAltBlock(blk blockchain.NodeHeader) bool { - blockNumber := blk.Number.Int64() - // If we've received the same block number from all nodes, check hashes there are some different versions - if len(rc.blockHashes[blockNumber]) >= rc.numberOfNodes { - firstBlockHash := rc.blockHashes[blockNumber][0] - for _, blockHash := range rc.blockHashes[blockNumber][1:] { - if blockHash.String() != firstBlockHash.String() { - return true - } - } - } - return false -} - -func (rc *ReorgController) compareBlocks(blk blockchain.NodeHeader) error { - if blk.NodeID == 0 && blk.Number.Int64() >= rc.forkBlockNumber && rc.isAltBlock(blk) { - rc.once.Do(func() { - log.Warn().Int64("Number", blk.Number.Int64()).Msg("Reorg started") - rc.reorgStarted <- struct{}{} - }) - rc.altBlockNumbers = append(rc.altBlockNumbers, blk.Number.Int64()) - rc.currentAltBlocks++ - log.Info(). - Int64("Number", blk.Number.Int64()). - Str("Hash", blk.Hash.String()). - Int("Node", blk.NodeID). - Int("BlocksLeft", rc.ReorgDepth-rc.currentAltBlocks). - Msg("Mined alternative block") - } - if rc.currentAltBlocks == rc.ReorgDepth { - log.Info().Msg("Joining network") - if err := rc.joinNetwork(); err != nil { - return err - } - rc.depthReached <- struct{}{} - rc.currentBlockConsensus = 0 - } - return nil -} - -// Wait wait until reorg is done -func (rc *ReorgController) Wait() error { - <-rc.ctx.Done() - rc.cfg.Network.DeleteHeaderEventSubscription("reorg") - if rc.complete { - return nil - } - return fmt.Errorf("timeout waiting for reorg to complete") -} - -// forkNetwork stomp the network between target reorged node and the rest -func (rc *ReorgController) forkNetwork(header blockchain.NodeHeader) error { - rc.forkBlockNumber = header.Number.Int64() - log.Debug(). - Int64("Number", rc.forkBlockNumber). - Str("Network", rc.cfg.Network.GetNetworkName()). - Msg("Forking network") - expName, err := rc.cfg.Env.Chaos.Run( - chaos.NewNetworkPartition( - rc.cfg.Env.Cfg.Namespace, - &chaos.Props{ - DurationStr: "999h", - FromLabels: &map[string]*string{"app": ptr.Ptr(reorg.TXNodesAppLabel)}, - ToLabels: &map[string]*string{"app": ptr.Ptr(reorg.MinerNodesAppLabel)}, - }, - )) - rc.chaosExperimentName = expName - rc.networkStep.Store(CheckBlocks) - return err -} - -// joinNetwork restores network connectivity between nodes -func (rc *ReorgController) joinNetwork() error { - return rc.cfg.Env.Chaos.Stop(rc.chaosExperimentName) -} - -// hasNetworkFormedConsensus waits for network to have N blocks with the same hashes -func (rc *ReorgController) hasNetworkFormedConsensus(header blockchain.NodeHeader) bool { - blockNumber := header.Number.Int64() - // If we've received the same block number from all nodes, check hashes to ensure they've reformed consensus - if len(rc.blockHashes[blockNumber]) >= rc.numberOfNodes { - firstBlockHash := rc.blockHashes[blockNumber][0] - for _, blockHash := range rc.blockHashes[blockNumber][1:] { - if blockHash.String() != firstBlockHash.String() { - return false - } - } - log.Debug(). - Int("Blocks left", rc.cfg.BlockConsensusThreshold-rc.currentBlockConsensus). - Msg("Waiting for consensus threshold") - rc.currentBlockConsensus++ - } - - if rc.currentBlockConsensus >= rc.cfg.BlockConsensusThreshold { - log.Info(). - Msg("Network joined") - return true - } - return false -} - -func (rc *ReorgController) appendBlockHeader(header blockchain.NodeHeader) { - bn := header.Number.Int64() - if _, ok := rc.blockHashes[bn]; !ok { - rc.blockHashes[bn] = []common.Hash{} - } - rc.blockHashes[bn] = append(rc.blockHashes[bn], header.Hash) - - if _, ok := rc.blocksByNode[header.NodeID]; !ok { - rc.blocksByNode[header.NodeID] = make(map[int64]blockchain.NodeHeader) - } - rc.blocksByNode[header.NodeID][bn] = header -} diff --git a/integration-tests/scripts/buildEvmClientTestMatrixList.sh b/integration-tests/scripts/buildEvmClientTestMatrixList.sh deleted file mode 100755 index 2f0e27b7fb..0000000000 --- a/integration-tests/scripts/buildEvmClientTestMatrixList.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash - -# requires a path to a json file with all the tests it should run -# requires a node label to be passed in, for example "ubuntu-latest" - -set -e - -# get this script's directory -SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) - -cd "$SCRIPT_DIR"/../ || exit 1 - -JSONFILE=$1 -NODE_LABEL=$2 - -COUNTER=1 - -# Build a JSON object in the format expected by our evm-version-compatibility-tests workflow matrix -matrix_output() { - local counter=$1 - local job_name=$2 - local test_name=$3 - local node_label=$4 - local eth_client=$5 - local docker_image=$6 - local product=$7 - local counter_out=$(printf "%02d\n" $counter) - echo -n "{\"name\": \"${job_name}-${counter_out}\", \"os\": \"${node_label}\", \"product\": \"${product}\", \"eth_client\": \"${eth_client}\", \"docker_image\": \"${docker_image}\", \"run\": \"-run '^${test_name}$'\"}" -} - -# Read the JSON file and loop through 'tests' and 'run' -jq -c '.tests[]' ${JSONFILE} | while read -r test; do - testName=$(echo ${test} | jq -r '.name') - label=$(echo ${test} | jq -r '.label // empty') - effective_node_label=${label:-$NODE_LABEL} - eth_client=$(echo ${test} | jq -r '.eth_client') - docker_image=$(echo ${test} | jq -r '.docker_image') - product=$(echo ${test} | jq -r '.product') - subTests=$(echo ${test} | jq -r '.run[]?.name // empty') - output="" - - if [ $COUNTER -ne 1 ]; then - echo -n "," - fi - - # Loop through subtests, if any, and print in the desired format - if [ -n "$subTests" ]; then - subTestString="" - subTestCounter=1 - for subTest in $subTests; do - if [ $subTestCounter -ne 1 ]; then - subTestString+="|" - fi - subTestString+="${testName}\/${subTest}" - ((subTestCounter++)) - done - testName="${subTestString}" - fi - matrix_output $COUNTER "emv-node-version-compatibility-test" "${testName}" ${effective_node_label} "${eth_client}" "${docker_image}" "${product}" - ((COUNTER++)) -done > "./tmpout.json" -OUTPUT=$(cat ./tmpout.json) -echo "[${OUTPUT}]" -rm ./tmpout.json \ No newline at end of file diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index cafeea67c1..46abccae56 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -11,6 +11,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/fxamacker/cbor/v2" @@ -22,10 +24,8 @@ import ( ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -37,7 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" ) const ( @@ -47,6 +47,20 @@ const ( defaultAmountOfUpkeeps = 2 ) +// UpgradeChainlinkNodeVersions upgrades all Chainlink nodes to a new version, and then runs the test environment +// to apply the upgrades +func upgradeChainlinkNodeVersionsLocal( + newImage, newVersion string, + nodes ...*test_env.ClNode, +) error { + for _, node := range nodes { + if err := node.UpgradeVersion(newImage, newVersion); err != nil { + return err + } + } + return nil +} + func automationDefaultRegistryConfig(c tc.AutomationTestConfig) contracts.KeeperRegistrySettings { registrySettings := c.GetAutomationConfig().AutomationConfig.RegistrySettings return contracts.KeeperRegistrySettings{ @@ -96,6 +110,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { "registry_2_2_with_mercury_v02": ethereum.RegistryVersion_2_2, "registry_2_2_with_mercury_v03": ethereum.RegistryVersion_2_2, "registry_2_2_with_logtrigger_and_mercury_v02": ethereum.RegistryVersion_2_2, + "registry_2_3_conditional": ethereum.RegistryVersion_2_3, } for n, rv := range registryVersions { @@ -127,7 +142,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -171,7 +186,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { startTime := time.Now() t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) // TODO Tune this timeout window after stress testing @@ -195,7 +210,7 @@ func SetupAutomationBasic(t *testing.T, nodeUpgrade bool) { expect := 5 // Upgrade the nodes one at a time and check that the upkeeps are still being performed for i := 0; i < 5; i++ { - err = actions.UpgradeChainlinkNodeVersionsLocal(*cfg.GetChainlinkUpgradeImageConfig().Image, *cfg.GetChainlinkUpgradeImageConfig().Version, a.DockerEnv.ClCluster.Nodes[i]) + err = upgradeChainlinkNodeVersionsLocal(*cfg.GetChainlinkUpgradeImageConfig().Image, *cfg.GetChainlinkUpgradeImageConfig().Version, a.DockerEnv.ClCluster.Nodes[i]) require.NoError(t, err, "Error when upgrading node %d", i) time.Sleep(time.Second * 10) expect = expect + 5 @@ -266,7 +281,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -288,7 +303,7 @@ func TestSetUpkeepTriggerConfig(t *testing.T) { } t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) l.Info().Msg("Waiting for all upkeeps to perform") @@ -447,7 +462,7 @@ func TestAutomationAddFunds(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -461,7 +476,7 @@ func TestAutomationAddFunds(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) l.Info().Msg("Making sure for 2m no upkeeps are performed") @@ -525,7 +540,7 @@ func TestAutomationPauseUnPause(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -539,7 +554,7 @@ func TestAutomationPauseUnPause(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -624,7 +639,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -638,7 +653,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -659,7 +674,7 @@ func TestAutomationRegisterUpkeep(t *testing.T) { } }, "4m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~1m for performing each upkeep once, ~2m buffer - newConsumers, _ := actions_seth.RegisterNewUpkeeps(t, a.ChainClient, a.LinkToken, + newConsumers, _ := actions.RegisterNewUpkeeps(t, a.ChainClient, a.LinkToken, a.Registry, a.Registrar, automationDefaultUpkeepGasLimit, 1) // We know that newConsumers has size 1, so we can just use the newly registered upkeep. @@ -718,7 +733,7 @@ func TestAutomationPauseRegistry(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -732,7 +747,7 @@ func TestAutomationPauseRegistry(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -796,7 +811,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -810,7 +825,7 @@ func TestAutomationKeeperNodesDown(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -902,7 +917,7 @@ func TestAutomationPerformSimulation(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumersPerformance, _ := actions_seth.DeployPerformanceConsumers( + consumersPerformance, _ := actions.DeployPerformanceConsumers( t, a.ChainClient, a.Registry, @@ -918,7 +933,7 @@ func TestAutomationPerformSimulation(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -973,7 +988,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumersPerformance, upkeepIDs := actions_seth.DeployPerformanceConsumers( + consumersPerformance, upkeepIDs := actions.DeployPerformanceConsumers( t, a.ChainClient, a.Registry, @@ -989,7 +1004,7 @@ func TestAutomationCheckPerformGasLimit(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -1128,7 +1143,7 @@ func TestUpdateCheckData(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - performDataChecker, upkeepIDs := actions_seth.DeployPerformDataCheckerConsumers( + performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerConsumers( t, a.ChainClient, a.Registry, @@ -1141,7 +1156,7 @@ func TestUpdateCheckData(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -1209,7 +1224,7 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { sb, err := a.ChainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - consumers, upkeepIDs := actions_seth.DeployConsumers( + consumers, upkeepIDs := actions.DeployConsumers( t, a.ChainClient, a.Registry, @@ -1223,7 +1238,7 @@ func TestSetOffchainConfigWithMaxGasPrice(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, a.Logger, a.ChainClient, sb, a.Registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -1348,7 +1363,6 @@ func setupAutomationTestDocker( l := logging.GetTestLogger(t) // Add registry version to config registryConfig.RegistryVersion = registryVersion - network := networks.MustGetSelectedNetworkConfig(automationTestConfig.GetNetworkConfig())[0] //launch the environment var env *test_env.CLClusterTestEnv @@ -1366,7 +1380,6 @@ func setupAutomationTestDocker( WithTestInstance(t). WithTestConfig(automationTestConfig). WithMockAdapter(). - WithoutEvmClients(). WithoutCleanup(). Build() require.NoError(t, err, "Error deploying test environment for Mercury") @@ -1388,9 +1401,7 @@ func setupAutomationTestDocker( WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithSecretsConfig(secretsConfig). WithCLNodes(clNodesCount). - WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment for Mercury") @@ -1402,18 +1413,27 @@ func setupAutomationTestDocker( WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(clNodesCount). - WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment") } nodeClients := env.ClCluster.NodeAPIs() - sethClient, err := env.GetSethClient(network.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(automationTestConfig, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + a := automationv2.NewAutomationTestDocker(l, sethClient, nodeClients) a.SetMercuryCredentialName("cred1") a.RegistrySettings = registryConfig diff --git a/integration-tests/smoke/automation_test.go_test_list.json b/integration-tests/smoke/automation_test.go_test_list.json index e8f0f838df..f0b8a1cb60 100644 --- a/integration-tests/smoke/automation_test.go_test_list.json +++ b/integration-tests/smoke/automation_test.go_test_list.json @@ -35,6 +35,13 @@ {"name":"registry_2_2_with_logtrigger_and_mercury_v02"} ] }, + { + "name": "TestAutomationBasic", + "nodes": 1, + "run":[ + {"name":"registry_2_3_conditional"} + ] + }, { "name": "TestSetUpkeepTriggerConfig", "nodes": 2 diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index e281824f0b..6f864b2e49 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -36,7 +36,6 @@ func TestCronBasic(t *testing.T) { WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) @@ -92,7 +91,6 @@ func TestCronJobReplacement(t *testing.T) { WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) diff --git a/integration-tests/smoke/evm_node_compatibility_test_list.json b/integration-tests/smoke/evm_node_compatibility_test_list.json deleted file mode 100644 index 45b303a0a2..0000000000 --- a/integration-tests/smoke/evm_node_compatibility_test_list.json +++ /dev/null @@ -1,184 +0,0 @@ -{ - "tests": [ - { - "product": "ocr", - "name": "TestOCRBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:latest_stable" - }, - { - "product": "ocr", - "name": "TestOCRBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.13.0" - }, - { - "product": "ocr", - "name": "TestOCRBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.12.0" - }, - { - "product": "ocr", - "name": "TestOCRBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.11.0" - }, - { - "product": "ocr", - "name": "TestOCRBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.10.0" - }, - { - "product": "ocr2", - "name": "TestOCRv2Request", - "eth_client": "geth", - "docker_image": "ethereum/client-go:latest_stable" - }, - { - "product": "ocr2", - "name": "TestOCRv2Request", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.13.0" - }, - { - "product": "ocr2", - "name": "TestOCRv2Request", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.12.0" - }, - { - "product": "ocr2", - "name": "TestOCRv2Request", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.11.0" - }, - { - "product": "ocr2", - "name": "TestOCRv2Request", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.10.0" - }, - { - "product": "vrf", - "name": "TestVRFBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:latest_stable" - }, - { - "product": "vrf", - "name": "TestVRFBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.13.0" - }, - { - "product": "vrf", - "name": "TestVRFBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.12.0" - }, - { - "product": "vrf", - "name": "TestVRFBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.11.0" - }, - { - "product": "vrf", - "name": "TestVRFBasic", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.10.0" - }, - { - "product": "vrfv2", - "name": "TestVRFv2Basic/Request Randomness", - "eth_client": "geth", - "docker_image": "ethereum/client-go:latest_stable" - }, - { - "product": "vrfv2", - "name": "TestVRFv2Basic/Request Randomness", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.13.0" - }, - { - "product": "vrfv2", - "name": "TestVRFv2Basic/Request Randomness", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.12.0" - }, - { - "product": "vrfv2", - "name": "TestVRFv2Basic/Request Randomness", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.11.0" - }, - { - "product": "vrfv2", - "name": "TestVRFv2Basic/Request Randomness", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.10.0" - }, - { - "product": "vrfv2plus", - "name": "TestVRFv2Plus/Link Billing", - "eth_client": "geth", - "docker_image": "ethereum/client-go:latest_stable" - }, - { - "product": "vrfv2plus", - "name": "TestVRFv2Plus/Link Billing", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.13.0" - }, - { - "product": "vrfv2plus", - "name": "TestVRFv2Plus/Link Billing", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.12.0" - }, - { - "product": "vrfv2plus", - "name": "TestVRFv2Plus/Link Billing", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.11.0" - }, - { - "product": "vrfv2plus", - "name": "TestVRFv2Plus/Link Billing", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.10.0" - }, - { - "product": "automation", - "name": "TestSetUpkeepTriggerConfig", - "eth_client": "geth", - "docker_image": "ethereum/client-go:latest_stable" - }, - { - "product": "automation", - "name": "TestSetUpkeepTriggerConfig", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.13.0" - }, - { - "product": "automation", - "name": "TestSetUpkeepTriggerConfig", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.12.0" - }, - { - "product": "automation", - "name": "TestSetUpkeepTriggerConfig", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.11.0" - }, - { - "product": "automation", - "name": "TestSetUpkeepTriggerConfig", - "eth_client": "geth", - "docker_image": "ethereum/client-go:v1.10.0" - } - ] -} \ No newline at end of file diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 4165e9b79b..05b75da223 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -13,11 +13,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -29,9 +28,7 @@ func TestFluxBasic(t *testing.T) { l := logging.GetTestLogger(t) config, err := tc.GetConfig("Smoke", tc.Flux) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") @@ -43,15 +40,16 @@ func TestFluxBasic(t *testing.T) { WithMockAdapter(). WithCLNodes(3). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) nodeAddresses, err := env.ClCluster.NodeAddresses() require.NoError(t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - sethClient, err := env.GetSethClient(network.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") adapterUUID := uuid.NewString() @@ -71,9 +69,14 @@ func TestFluxBasic(t *testing.T) { err = fluxInstance.UpdateAvailableFunds() require.NoError(t, err, "Updating the available funds on the Flux Aggregator Contract shouldn't fail") - err = env.FundChainlinkNodes(big.NewFloat(1)) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Failed to fund the nodes") + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + err = fluxInstance.SetOracles( contracts.FluxAggregatorSetOraclesOptions{ AddList: nodeAddresses, @@ -115,7 +118,7 @@ func TestFluxBasic(t *testing.T) { // initial value set is performed before jobs creation fluxRoundTimeout := 1 * time.Minute - err = actions_seth.WatchNewFluxRound(l, sethClient, 1, fluxInstance, fluxRoundTimeout) + err = actions.WatchNewFluxRound(l, sethClient, 1, fluxInstance, fluxRoundTimeout) require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") data, err := fluxInstance.GetContractData(testcontext.Get(t)) require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail") @@ -132,7 +135,7 @@ func TestFluxBasic(t *testing.T) { err = env.MockAdapter.SetAdapterBasedIntValuePath(adapterPath, []string{http.MethodPost}, 1e10) require.NoError(t, err, "Setting value path in mock server shouldn't fail") - err = actions_seth.WatchNewFluxRound(l, sethClient, 2, fluxInstance, fluxRoundTimeout) + err = actions.WatchNewFluxRound(l, sethClient, 2, fluxInstance, fluxRoundTimeout) require.NoError(t, err, "Waiting for event subscriptions in nodes shouldn't fail") data, err = fluxInstance.GetContractData(testcontext.Get(t)) require.NoError(t, err, "Getting contract data from flux aggregator contract shouldn't fail") diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 1783549637..0377553191 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -6,15 +6,15 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -25,9 +25,7 @@ func TestForwarderOCRBasic(t *testing.T) { l := logging.GetTestLogger(t) config, err := tc.GetConfig("Smoke", tc.ForwarderOcr) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") @@ -38,9 +36,7 @@ func TestForwarderOCRBasic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) @@ -50,32 +46,42 @@ func TestForwarderOCRBasic(t *testing.T) { workerNodeAddresses, err := actions.ChainlinkNodeAddressesLocal(workerNodes) require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + lt, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") fundingAmount := big.NewFloat(.05) l.Info().Str("ETH amount per node", fundingAmount.String()).Msg("Funding Chainlink nodes") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) require.NoError(t, err, "Error funding Chainlink nodes") - operators, authorizedForwarders, _ := actions_seth.DeployForwarderContracts( + operators, authorizedForwarders, _ := actions.DeployForwarderContracts( t, sethClient, common.HexToAddress(lt.Address()), len(workerNodes), ) require.Equal(t, len(workerNodes), len(operators), "Number of operators should match number of worker nodes") for i := range workerNodes { - actions_seth.AcceptAuthorizedReceiversOperator( + actions.AcceptAuthorizedReceiversOperator( t, l, sethClient, operators[i], authorizedForwarders[i], []common.Address{workerNodeAddresses[i]}, ) require.NoError(t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions_seth.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) + actions.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) } - ocrInstances, err := actions_seth.DeployOCRContractsForwarderFlow( + ocrInstances, err := actions.DeployOCRContractsForwarderFlow( l, sethClient, 1, @@ -87,7 +93,7 @@ func TestForwarderOCRBasic(t *testing.T) { err = actions.CreateOCRJobsWithForwarderLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, fmt.Sprint(sethClient.ChainID)) require.NoError(t, err, "failed to setup forwarder jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCR round") answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -96,7 +102,7 @@ func TestForwarderOCRBasic(t *testing.T) { err = actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCR round") answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 2651a02fb4..3970a0b43b 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -7,15 +7,15 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -26,9 +26,7 @@ func TestForwarderOCR2Basic(t *testing.T) { l := logging.GetTestLogger(t) config, err := tc.GetConfig("Smoke", tc.ForwarderOcr2) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") privateNetwork, err := actions.EthereumNetworkConfigFromConfig(l, &config) require.NoError(t, err, "Error building ethereum network config") @@ -39,9 +37,7 @@ func TestForwarderOCR2Basic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) @@ -51,30 +47,40 @@ func TestForwarderOCR2Basic(t *testing.T) { workerNodeAddresses, err := actions.ChainlinkNodeAddressesLocal(workerNodes) require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + lt, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") fundingAmount := big.NewFloat(.05) l.Info().Str("ETH amount per node", fundingAmount.String()).Msg("Funding Chainlink nodes") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), fundingAmount) require.NoError(t, err, "Error funding Chainlink nodes") - operators, authorizedForwarders, _ := actions_seth.DeployForwarderContracts( + operators, authorizedForwarders, _ := actions.DeployForwarderContracts( t, sethClient, common.HexToAddress(lt.Address()), len(workerNodes), ) require.Equal(t, len(workerNodes), len(operators), "Number of operators should match number of worker nodes") for i := range workerNodes { - actions_seth.AcceptAuthorizedReceiversOperator( + actions.AcceptAuthorizedReceiversOperator( t, l, sethClient, operators[i], authorizedForwarders[i], []common.Address{workerNodeAddresses[i]}, ) require.NoError(t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions_seth.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) + actions.TrackForwarder(t, sethClient, authorizedForwarders[i], workerNodes[i]) } // Gather transmitters @@ -84,20 +90,20 @@ func TestForwarderOCR2Basic(t *testing.T) { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - ocrInstances, err := actions_seth.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(lt.Address()), transmitters, ocrOffchainOptions) + ocrInstances, err := actions.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(lt.Address()), transmitters, ocrOffchainOptions) require.NoError(t, err, "Error deploying OCRv2 contracts with forwarders") ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) require.NoError(t, err, "Error building OCRv2 config") ocrv2Config.Transmitters = authorizedForwarders - err = actions_seth.ConfigureOCRv2AggregatorContracts(ocrv2Config, ocrInstances) + err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, ocrInstances) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), true, false) require.NoError(t, err, "Error creating OCRv2 jobs with forwarders") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCRv2 round") answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -108,7 +114,7 @@ func TestForwarderOCR2Basic(t *testing.T) { ocrRoundVal := (5 + i) % 10 err = env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, ocrRoundVal) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, int64(i), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, int64(i), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) require.NoError(t, err, "error watching for new OCRv2 round") answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) require.NoError(t, err, "Error getting latest OCRv2 answer") diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 62a79f0347..21e1aa6e08 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/onsi/gomega" "github.com/rs/zerolog" @@ -15,11 +17,9 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -97,7 +97,7 @@ func TestKeeperBasicSmoke(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -109,7 +109,7 @@ func TestKeeperBasicSmoke(t *testing.T) { ) t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) _, err = actions.CreateKeeperJobsLocal(l, chainlinkNodes, registry, contracts.OCRv2Config{}, fmt.Sprint(chainClient.ChainID)) @@ -178,7 +178,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, highBCPTRegistryConfig, @@ -193,7 +193,7 @@ func TestKeeperBlockCountPerTurn(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) keepersPerformedLowFreq := map[*big.Int][]string{} @@ -322,7 +322,7 @@ func TestKeeperSimulation(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumersPerformance, upkeepIDs := actions_seth.DeployPerformanceKeeperContracts( + registry, _, consumersPerformance, upkeepIDs := actions.DeployPerformanceKeeperContracts( t, chainClient, registryVersion, @@ -341,7 +341,7 @@ func TestKeeperSimulation(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) consumerPerformance := consumersPerformance[0] @@ -401,7 +401,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumersPerformance, upkeepIDs := actions_seth.DeployPerformanceKeeperContracts( + registry, _, consumersPerformance, upkeepIDs := actions.DeployPerformanceKeeperContracts( t, chainClient, registryVersion, @@ -420,7 +420,7 @@ func TestKeeperCheckPerformGasLimit(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) gom := gomega.NewGomegaWithT(t) @@ -538,7 +538,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, registrar, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, registrar, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -552,7 +552,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -576,7 +576,7 @@ func TestKeeperRegisterUpkeep(t *testing.T) { return nil }, "1m", "1s").Should(gomega.Succeed()) - newConsumers, _ := actions_seth.RegisterNewUpkeeps(t, chainClient, linkToken, + newConsumers, _ := actions.RegisterNewUpkeeps(t, chainClient, linkToken, registry, registrar, keeperDefaultUpkeepGasLimit, 1) // We know that newConsumers has size 1, so we can just use the newly registered upkeep. @@ -634,7 +634,7 @@ func TestKeeperAddFunds(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -649,7 +649,7 @@ func TestKeeperAddFunds(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) // Since the upkeep is currently underfunded, check that it doesn't get executed @@ -709,7 +709,7 @@ func TestKeeperRemove(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -724,7 +724,7 @@ func TestKeeperRemove(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -794,7 +794,7 @@ func TestKeeperPauseRegistry(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, @@ -810,7 +810,7 @@ func TestKeeperPauseRegistry(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) // Observe that the upkeeps which are initially registered are performing @@ -860,7 +860,7 @@ func TestKeeperMigrateRegistry(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_2, keeperDefaultRegistryConfig, @@ -875,11 +875,11 @@ func TestKeeperMigrateRegistry(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_2)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_2)() }) // Deploy the second registry, second registrar, and the same number of upkeeps as the first one - secondRegistry, _, _, _ := actions_seth.DeployKeeperContracts( + secondRegistry, _, _, _ := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_2, keeperDefaultRegistryConfig, @@ -964,7 +964,7 @@ func TestKeeperNodeDown(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, lowBCPTRegistryConfig, @@ -979,7 +979,7 @@ func TestKeeperNodeDown(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, registryVersion)() }) var initialCounters = make([]*big.Int, len(upkeepIDs)) @@ -1074,7 +1074,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, ethereum.RegistryVersion_1_3, lowBCPTRegistryConfig, @@ -1089,7 +1089,7 @@ func TestKeeperPauseUnPauseUpkeep(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() }) gom := gomega.NewGomegaWithT(t) @@ -1166,7 +1166,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { sb, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get start block") - registry, _, performDataChecker, upkeepIDs := actions_seth.DeployPerformDataCheckerContracts( + registry, _, performDataChecker, upkeepIDs := actions.DeployPerformDataCheckerContracts( t, chainClient, ethereum.RegistryVersion_1_3, @@ -1182,7 +1182,7 @@ func TestKeeperUpdateCheckData(t *testing.T) { require.NoError(t, err, "Error creating keeper jobs") t.Cleanup(func() { - actions_seth.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() + actions.GetStalenessReportCleanupFn(t, l, chainClient, sb, registry, ethereum.RegistryVersion_1_3)() }) gom := gomega.NewGomegaWithT(t) @@ -1236,16 +1236,23 @@ func setupKeeperTest(l zerolog.Logger, t *testing.T, config *tc.TestConfig) ( WithTestConfig(config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(5). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment") - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) + require.NoError(t, err, "Error getting seth client") + + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") - sethClient, err := env.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting EVM client shouldn't fail") + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) linkTokenContract, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") @@ -1261,7 +1268,7 @@ func TestKeeperJobReplacement(t *testing.T) { require.NoError(t, err, "Failed to get config") chainClient, chainlinkNodes, linkToken, _ := setupKeeperTest(l, t, &config) - registry, _, consumers, upkeepIDs := actions_seth.DeployKeeperContracts( + registry, _, consumers, upkeepIDs := actions.DeployKeeperContracts( t, registryVersion, keeperDefaultRegistryConfig, diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index 1f77b3a625..05be29a90b 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/onsi/gomega" "github.com/rs/zerolog" @@ -14,10 +16,9 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/testreporters" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" @@ -94,7 +95,7 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli require.NoError(t, err, "Error getting config") overrideEphemeralAddressesCount(&testConfig) - eventsToEmit := []abi.Event{} + var eventsToEmit []abi.Event for _, event := range logpoller.EmitterABI.Events { eventsToEmit = append(eventsToEmit, event) } @@ -107,6 +108,12 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli lpTestEnv := prepareEnvironment(l, t, &testConfig, logScannerSettings) testEnv := lpTestEnv.testEnv + sethClient := lpTestEnv.sethClient + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(testEnv.ClCluster.NodeAPIs())) + }) ctx := testcontext.Get(t) @@ -117,12 +124,8 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli l.Info().Msg("No duplicate filters found. OK!") - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - sethClient, err := testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - expectedFilters := logpoller.GetExpectedFilters(lpTestEnv.logEmitters, cfg) - waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, testEnv, &testConfig, expectedFilters) + waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, lpTestEnv, expectedFilters) // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) @@ -135,7 +138,7 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli // Start chaos experimnents by randomly pausing random containers (Chainlink nodes or their DBs) chaosDoneCh := make(chan error, 1) go func() { - logpoller.ExecuteChaosExperiment(l, testEnv, &testConfig, chaosDoneCh) + logpoller.ExecuteChaosExperiment(l, testEnv, sethClient, &testConfig, chaosDoneCh) }() totalLogsEmitted, err := logpoller.ExecuteGenerator(t, cfg, sethClient, lpTestEnv.logEmitters) @@ -175,7 +178,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { require.NoError(t, err, "Error getting config") overrideEphemeralAddressesCount(&testConfig) - eventsToEmit := []abi.Event{} + var eventsToEmit []abi.Event for _, event := range logpoller.EmitterABI.Events { eventsToEmit = append(eventsToEmit, event) } @@ -188,11 +191,16 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { lpTestEnv := prepareEnvironment(l, t, &testConfig, test_env.DefaultChainlinkNodeLogScannerSettings) testEnv := lpTestEnv.testEnv + sethClient := lpTestEnv.sethClient + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(testEnv.ClCluster.NodeAPIs())) + }) ctx := testcontext.Get(t) - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - sethClient, err := testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") + evmNetwork, err := testEnv.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) @@ -211,7 +219,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { eb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") - endBlock, err := logpoller.GetEndBlockToWaitFor(int64(eb), network, cfg) + endBlock, err := logpoller.GetEndBlockToWaitFor(int64(eb), *evmNetwork, cfg) require.NoError(t, err, "Error getting end block to wait for") l.Info().Int64("Ending Block", endBlock).Int("Total logs emitted", totalLogsEmitted).Int64("Expected total logs emitted", expectedLogsEmitted).Str("Duration", fmt.Sprintf("%d sec", duration)).Str("LPS", fmt.Sprintf("%d/sec", totalLogsEmitted/duration)).Msg("FINISHED EVENT EMISSION") @@ -228,7 +236,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { err = logpoller.RegisterFiltersAndAssertUniquness(l, lpTestEnv.registry, lpTestEnv.upkeepIDs, lpTestEnv.logEmitters, cfg, lpTestEnv.upKeepsNeeded) require.NoError(t, err, "Error registering filters") - waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, testEnv, &testConfig, expectedFilters) + waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx, l, coreLogger, t, lpTestEnv, expectedFilters) blockFinalisationWaitDuration := "5m" l.Warn().Str("Duration", blockFinalisationWaitDuration).Msg("Waiting for all CL nodes to have end block finalised") @@ -262,6 +270,7 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { } type logPollerEnvironment struct { + sethClient *seth.Client logEmitters []*contracts.LogEmitter testEnv *test_env.CLClusterTestEnv registry contracts.KeeperRegistry @@ -297,7 +306,7 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfi logScannerSettings, ) - _, upkeepIDs := actions_seth.DeployConsumers( + _, upkeepIDs := actions.DeployConsumers( t, chainClient, registry, @@ -326,16 +335,16 @@ func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfi upkeepIDs: upkeepIDs, upKeepsNeeded: upKeepsNeeded, testEnv: testEnv, + sethClient: chainClient, } } // waitForAllNodesToHaveExpectedFiltersRegisteredOrFail waits until all nodes have expected filters registered until timeout -func waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx context.Context, l zerolog.Logger, coreLogger core_logger.SugaredLogger, t *testing.T, testEnv *test_env.CLClusterTestEnv, testConfig *tc.TestConfig, expectedFilters []logpoller.ExpectedFilter) { +func waitForAllNodesToHaveExpectedFiltersRegisteredOrFail(ctx context.Context, l zerolog.Logger, coreLogger core_logger.SugaredLogger, t *testing.T, lpTestEnv logPollerEnvironment, expectedFilters []logpoller.ExpectedFilter) { // Make sure that all nodes have expected filters registered before starting to emit events - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - sethClient, err := testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") + sethClient := lpTestEnv.sethClient + testEnv := lpTestEnv.testEnv gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { @@ -372,13 +381,9 @@ func conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l zerolog.Logger, coreLogge logCountWaitDuration, err := time.ParseDuration(waitDuration) require.NoError(t, err, "Error parsing log count wait duration") - network := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] - chainClient, err := lpTestEnv.testEnv.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - allNodesHaveAllExpectedLogs := false if !allNodesLogCountMatches { - missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, chainClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) + missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, lpTestEnv.sethClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) if err == nil { if !missingLogs.IsEmpty() { logpoller.PrintMissingLogsInfo(missingLogs, l, testConfig.LogPoller) @@ -402,7 +407,7 @@ func conditionallyWaitUntilNodesHaveTheSameLogsAsEvm(l zerolog.Logger, coreLogge gom := gomega.NewGomegaWithT(t) gom.Eventually(func(g gomega.Gomega) { - missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, chainClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) + missingLogs, err := logpoller.GetMissingLogs(startBlock, endBlock, lpTestEnv.logEmitters, lpTestEnv.sethClient, lpTestEnv.testEnv.ClCluster, l, coreLogger, testConfig.LogPoller) if err != nil { l.Warn(). Err(err). diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index d0d1e36c8e..09a9a22249 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" @@ -15,13 +17,11 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -62,7 +62,7 @@ func TestOCRv2Basic(t *testing.T) { err := testEnv.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err) roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) @@ -84,9 +84,9 @@ func TestOCRv2Request(t *testing.T) { // Keep the mockserver value the same and continually request new rounds for round := 2; round <= 4; round++ { - err := actions_seth.StartNewRound(contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts)) + err := actions.StartNewRound(contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts)) require.NoError(t, err, "Error starting new OCR2 round") - err = actions_seth.WatchNewOCRRound(l, sethClient, int64(round), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, int64(round), contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(int64(round))) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") @@ -108,7 +108,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err := env.MockAdapter.SetAdapterBasedIntValuePath("ocr2", []string{http.MethodGet, http.MethodPost}, 10) require.NoError(t, err) - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(2)) @@ -127,7 +127,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) require.NoError(t, err, "Error creating OCRv2 jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) + err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err = aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(3)) @@ -156,14 +156,14 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, WithMockAdapter(). WithCLNodes(clNodeCount). WithCLNodeOptions(test_env.WithNodeEnvVars(testData.env)). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := testEnv.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := testEnv.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") nodeClients := testEnv.ClCluster.NodeAPIs() @@ -172,9 +172,14 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, linkContract, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Error deploying link token contract") - err = actions_seth.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(.05)) + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) require.NoError(t, err, "Error funding Chainlink nodes") + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(testEnv.ClCluster.NodeAPIs())) + }) + // Gather transmitters var transmitters []string for _, node := range workerNodes { @@ -186,7 +191,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - aggregatorContracts, err := actions_seth.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions) + aggregatorContracts, err := actions.DeployOCRv2Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), transmitters, ocrOffchainOptions) require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) @@ -195,12 +200,12 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, ocrv2Config, err := actions.BuildMedianOCR2ConfigLocal(workerNodes, ocrOffchainOptions) require.NoError(t, err, "Error building OCRv2 config") - err = actions_seth.ConfigureOCRv2AggregatorContracts(ocrv2Config, aggregatorContracts) + err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, aggregatorContracts) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") assertCorrectNodeConfiguration(t, l, clNodeCount, testData, testEnv) - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*5) require.NoError(t, err, "Error watching for new OCR2 round") roundData, err := aggregatorContracts[0].GetRound(testcontext.Get(t), big.NewInt(1)) require.NoError(t, err, "Getting latest answer from OCR contract shouldn't fail") @@ -214,7 +219,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, func assertCorrectNodeConfiguration(t *testing.T, l zerolog.Logger, totalNodeCount int, testData ocr2test, testEnv *test_env.CLClusterTestEnv) { expectedNodesWithConfiguration := totalNodeCount - 1 // minus bootstrap node - expectedPatterns := []string{} + var expectedPatterns []string if testData.env[string(env.MedianPlugin.Cmd)] != "" { expectedPatterns = append(expectedPatterns, "Registered loopp.*OCR2.*Median.*") diff --git a/integration-tests/smoke/ocr2vrf_test.go b/integration-tests/smoke/ocr2vrf_test.go index fe6515df03..b99e313a02 100644 --- a/integration-tests/smoke/ocr2vrf_test.go +++ b/integration-tests/smoke/ocr2vrf_test.go @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/ocr2vrf_actions/ocr2vrf_constants" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -33,10 +32,10 @@ var ocr2vrfSmokeConfig *testconfig.TestConfig func TestOCR2VRFRedeemModel(t *testing.T) { t.Parallel() - // remember to add TOML config for Chainlink node before trying to run this test in future + // remember to add TOML testConfig for Chainlink node before trying to run this test in future t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) - config, err := testconfig.GetConfig("Smoke", testconfig.OCR2) + testConfig, err := testconfig.GetConfig("Smoke", testconfig.OCR2) if err != nil { t.Fatal(err) } @@ -47,7 +46,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) { } testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(config, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(testConfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -56,7 +55,7 @@ func TestOCR2VRFRedeemModel(t *testing.T) { require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &testConfig) require.NoError(t, err, "Error tearing down environment") }) @@ -99,7 +98,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { t.Parallel() t.Skip("VRFv3 is on pause, skipping") l := logging.GetTestLogger(t) - config, err := testconfig.GetConfig("Smoke", testconfig.OCR2) + testConfig, err := testconfig.GetConfig("Smoke", testconfig.OCR2) if err != nil { t.Fatal(err) } @@ -110,7 +109,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { } testNetwork = seth_utils.MustReplaceSimulatedNetworkUrlWithK8(l, testNetwork, *testEnvironment) - chainClient, err := actions_seth.GetChainClientWithConfigFunction(config, testNetwork, actions_seth.OneEphemeralKeysLiveTestnetCheckFn) + chainClient, err := seth_utils.GetChainClientWithConfigFunction(testConfig, testNetwork, seth_utils.OneEphemeralKeysLiveTestnetCheckFn) require.NoError(t, err, "Error creating seth client") chainlinkNodes, err := client.ConnectChainlinkNodes(testEnvironment) @@ -119,7 +118,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { require.NoError(t, err, "Retreiving on-chain wallet addresses for chainlink nodes shouldn't fail") t.Cleanup(func() { - err := actions_seth.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &config) + err := actions.TeardownSuite(t, chainClient, testEnvironment, chainlinkNodes, nil, zapcore.ErrorLevel, &testConfig) require.NoError(t, err, "Error tearing down environment") }) @@ -160,9 +159,7 @@ func TestOCR2VRFFulfillmentModel(t *testing.T) { func setupOCR2VRFEnvironment(t *testing.T) (testEnvironment *environment.Environment, testNetwork blockchain.EVMNetwork) { if ocr2vrfSmokeConfig == nil { c, err := testconfig.GetConfig("Smoke", testconfig.OCR2VRF) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err, "Error getting config") ocr2vrfSmokeConfig = &c } diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 02d548f476..d989517278 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -5,17 +5,17 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -36,7 +36,7 @@ func TestOCRBasic(t *testing.T) { err := actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err, "Error setting all adapter responses to the same value") - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, ErrWatchingNewOCRRound) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -54,7 +54,7 @@ func TestOCRJobReplacement(t *testing.T) { err := actions.SetAllAdapterResponsesToTheSameValueLocal(10, ocrInstances, workerNodes, env.MockAdapter) require.NoError(t, err, "Error setting all adapter responses to the same value") - err = actions_seth.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 2, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, ErrWatchingNewOCRRound) answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -71,7 +71,7 @@ func TestOCRJobReplacement(t *testing.T) { err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, big.NewInt(sethClient.ChainID)) require.NoError(t, err, "Error creating OCR jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, ErrWatchingNewOCRRound) answer, err = ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) @@ -94,29 +94,37 @@ func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - selectedNetwork := networks.MustGetSelectedNetworkConfig(config.Network)[0] - sethClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") nodeClients := env.ClCluster.NodeAPIs() bootstrapNode, workerNodes := nodeClients[0], nodeClients[1:] + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Error funding Chainlink nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + linkContract, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Error deploying link token contract") - ocrInstances, err := actions_seth.DeployOCRv1Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes)) + ocrInstances, err := actions.DeployOCRv1Contracts(l, sethClient, 1, common.HexToAddress(linkContract.Address()), contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(workerNodes)) require.NoError(t, err, "Error deploying OCR contracts") err = actions.CreateOCRJobsLocal(ocrInstances, bootstrapNode, workerNodes, 5, env.MockAdapter, big.NewInt(sethClient.ChainID)) require.NoError(t, err, "Error creating OCR jobs") - err = actions_seth.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) + err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V1OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(3*time.Minute)) require.NoError(t, err, "Error watching for new OCR round") answer, err := ocrInstances[0].GetLatestAnswer(testcontext.Get(t)) diff --git a/integration-tests/smoke/reorg_above_finality_test.go b/integration-tests/smoke/reorg_above_finality_test.go new file mode 100644 index 0000000000..829aa66fdc --- /dev/null +++ b/integration-tests/smoke/reorg_above_finality_test.go @@ -0,0 +1,94 @@ +package smoke + +import ( + "testing" + "time" + + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink/integration-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" +) + +func TestReorgAboveFinality_FinalityTagDisabled(t *testing.T) { + t.Parallel() + + l := logging.GetTestLogger(t) + config, err := tc.GetConfig(t.Name(), tc.LogPoller) + require.NoError(t, err, "Error getting config") + + privateNetworkConf, err := actions.EthereumNetworkConfigFromConfig(l, &config) + require.NoError(t, err) + + // Get values from the node config + configMap := make(map[string]interface{}) + err = toml.Unmarshal([]byte(config.NodeConfig.CommonChainConfigTOML), &configMap) + require.NoError(t, err, "Error unmarshaling TOML") + nodeFinalityDepthInt, isFinalityDepthSet := configMap["FinalityDepth"].(int64) + nodeFinalityTagEnabled := configMap["FinalityTagEnabled"].(bool) + l.Info().Int64("nodeFinalityDepth", nodeFinalityDepthInt).Bool("nodeFinalityTagEnabled", nodeFinalityTagEnabled).Msg("Node reorg config") + + var reorgDepth int + if isFinalityDepthSet { + reorgDepth = int(nodeFinalityDepthInt) + 5 + } else { + reorgDepth = 15 + } + minChainBlockNumberBeforeReorg := reorgDepth + 10 + + testEnv, err := test_env.NewCLTestEnvBuilder(). + WithTestInstance(t). + WithTestConfig(&config). + WithPrivateEthereumNetwork(privateNetworkConf.EthereumNetworkConfig). + WithCLNodes(6). + WithoutCleanup(). + Build() + require.NoError(t, err) + + evmNetwork, err := testEnv.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + client := ctf_client.NewRPCClient(evmNetwork.HTTPURLs[0]) + + // Wait for chain to progress + require.Eventually(t, func() bool { + bn, err := client.BlockNumber() + require.NoError(t, err) + l.Info().Int64("blockNumber", bn).Int("targetBlockNumber", minChainBlockNumberBeforeReorg).Msg("Waiting for chain to progress above target block number") + return bn >= int64(minChainBlockNumberBeforeReorg) + }, 8*time.Minute, 3*time.Second, "timeout exceeded: chain did not progress above the target block number") + + // Run reorg above finality depth + l.Info(). + Str("URL", client.URL). + Int64("nodeFinalityDepth", nodeFinalityDepthInt). + Int("reorgDepth", reorgDepth). + Msg("Starting blockchain reorg on Simulated Geth chain") + err = client.GethSetHead(reorgDepth) + require.NoError(t, err, "Error starting blockchain reorg on Simulated Geth chain") + + l.Info().Msg("Waiting for all nodes to report finality violation") + nodes := testEnv.ClCluster.NodeAPIs() + require.Eventually(t, func() bool { + violatedResponses := 0 + for _, node := range nodes { + resp, _, err := node.Health() + require.NoError(t, err) + for _, d := range resp.Data { + if d.Attributes.Name == "EVM.1337.LogPoller" && d.Attributes.Output == "finality violated" && d.Attributes.Status == "failing" { + violatedResponses++ + } + } + l.Info().Msgf("Resp: %v", resp) + } + + l.Info().Int("violatedResponses", violatedResponses).Int("nodes", len(nodes)).Msg("Checking if all nodes reported finality violation") + return violatedResponses == len(nodes) + }, 3*time.Minute, 5*time.Second, "not all the nodes report finality violation") + l.Info().Msg("All nodes reported finality violation") +} diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 7090564c42..862ac911b3 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -7,12 +7,13 @@ import ( "strings" "testing" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/google/uuid" "github.com/onsi/gomega" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -39,16 +40,24 @@ func TestRunLogBasic(t *testing.T) { WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - sethClient, err := env.GetSethClient(network.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) + lt, err := contracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index abb619e7b0..0f706f1576 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -13,12 +13,13 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv1" "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" ethcontracts "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" @@ -27,7 +28,7 @@ import ( func TestVRFBasic(t *testing.T) { t.Parallel() l := logging.GetTestLogger(t) - env, contracts, sethClient := prepareVRFtestEnv(t, l) + env, vrfContracts, sethClient := prepareVRFtestEnv(t, l) for _, n := range env.ClCluster.Nodes { nodeKey, err := n.API.MustCreateVRFKey() @@ -36,13 +37,13 @@ func TestVRFBasic(t *testing.T) { pubKeyCompressed := nodeKey.Data.ID jobUUID := uuid.New() os := &client.VRFTxPipelineSpec{ - Address: contracts.Coordinator.Address(), + Address: vrfContracts.Coordinator.Address(), } ost, err := os.String() require.NoError(t, err, "Building observation source spec shouldn't fail") job, err := n.API.MustCreateJob(&client.VRFJobSpec{ Name: fmt.Sprintf("vrf-%s", jobUUID), - CoordinatorAddress: contracts.Coordinator.Address(), + CoordinatorAddress: vrfContracts.Coordinator.Address(), MinIncomingConfirmations: 1, PublicKey: pubKeyCompressed, ExternalJobID: jobUUID.String(), @@ -55,7 +56,7 @@ func TestVRFBasic(t *testing.T) { require.NoError(t, err, "Getting primary ETH address of chainlink node shouldn't fail") provingKey, err := actions.EncodeOnChainVRFProvingKey(*nodeKey) require.NoError(t, err, "Encoding on-chain VRF Proving key shouldn't fail") - err = contracts.Coordinator.RegisterProvingKey( + err = vrfContracts.Coordinator.RegisterProvingKey( big.NewInt(1), oracleAddr, provingKey, @@ -66,9 +67,9 @@ func TestVRFBasic(t *testing.T) { encodedProvingKeys = append(encodedProvingKeys, provingKey) //nolint:gosec // G602 - requestHash, err := contracts.Coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0]) + requestHash, err := vrfContracts.Coordinator.HashOfKey(testcontext.Get(t), encodedProvingKeys[0]) require.NoError(t, err, "Getting Hash of encoded proving keys shouldn't fail") - err = contracts.Consumer.RequestRandomness(requestHash, big.NewInt(1)) + err = vrfContracts.Consumer.RequestRandomness(requestHash, big.NewInt(1)) require.NoError(t, err, "Requesting randomness shouldn't fail") gom := gomega.NewGomegaWithT(t) @@ -77,7 +78,7 @@ func TestVRFBasic(t *testing.T) { jobRuns, err := env.ClCluster.Nodes[0].API.MustReadRunsByJob(job.Data.ID) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Job execution shouldn't fail") - out, err := contracts.Consumer.RandomnessOutput(testcontext.Get(t)) + out, err := vrfContracts.Consumer.RandomnessOutput(testcontext.Get(t)) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "Getting the randomness output of the consumer shouldn't fail") // Checks that the job has actually run g.Expect(len(jobRuns.Data)).Should(gomega.BeNumerically(">=", 1), @@ -196,25 +197,33 @@ func prepareVRFtestEnv(t *testing.T, l zerolog.Logger) (*test_env.CLClusterTestE WithTestConfig(&config). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). - WithFunding(big.NewFloat(*config.Common.ChainlinkNodeFunding)). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err) - network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] - sethClient, err := env.GetSethClient(network.ChainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + sethClient, err := seth_utils.GetChainClient(config, *evmNetwork) + require.NoError(t, err, "Error getting seth client") + + err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + + t.Cleanup(func() { + // ignore error, we will see failures in the logs anyway + _ = actions.ReturnFundsFromNodes(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs())) + }) lt, err := ethcontracts.DeployLinkTokenContract(l, sethClient) require.NoError(t, err, "Deploying Link Token Contract shouldn't fail") - contracts, err := vrfv1.DeployVRFContracts(sethClient, lt.Address()) + vrfContracts, err := vrfv1.DeployVRFContracts(sethClient, lt.Address()) require.NoError(t, err, "Deploying VRF Contracts shouldn't fail") - err = lt.Transfer(contracts.Consumer.Address(), big.NewInt(2e18)) + err = lt.Transfer(vrfContracts.Consumer.Address(), big.NewInt(2e18)) require.NoError(t, err, "Funding consumer contract shouldn't fail") _, err = ethcontracts.DeployVRFv1Contract(sethClient) require.NoError(t, err, "Deploying VRF contract shouldn't fail") - return env, contracts, sethClient + return env, vrfContracts, sethClient } diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index d78987059d..de40322672 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -10,6 +10,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -47,6 +49,7 @@ func TestVRFv2Basic(t *testing.T) { subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -56,8 +59,6 @@ func TestVRFv2Basic(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -86,17 +87,13 @@ func TestVRFv2Basic(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - t.Run("Request Randomness", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForRequestRandomness, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -152,8 +149,7 @@ func TestVRFv2Basic(t *testing.T) { testConfig := configCopy.VRFv2.General consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -198,8 +194,7 @@ func TestVRFv2Basic(t *testing.T) { t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForJobRuns, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -243,8 +238,7 @@ func TestVRFv2Basic(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) wrapperContracts, wrapperSubID, err := vrfv2.SetupVRFV2WrapperEnvironment( testcontext.Get(t), - testEnv, - chainID, + sethClient, &configCopy, vrfContracts.LinkToken, vrfContracts.MockETHLINKFeed, @@ -321,8 +315,7 @@ func TestVRFv2Basic(t *testing.T) { t.Run("Oracle Withdraw", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForOracleWithDraw, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -380,8 +373,7 @@ func TestVRFv2Basic(t *testing.T) { t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) _, subIDsForCancelling, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -460,8 +452,7 @@ func TestVRFv2Basic(t *testing.T) { configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForOwnerCancelling, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -575,6 +566,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -586,8 +578,6 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { vrfv2Config := config.VRFv2 cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -616,15 +606,14 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") t.Run("Request Randomness with multiple sending keys", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForMultipleSendingKeys, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -661,8 +650,6 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { 0, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") fulfillmentTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), randomWordsFulfilledEvent.Raw.TxHash) require.NoError(t, err, "error getting tx from hash") fulfillmentTxFromAddress, err := actions.GetTxFromAddress(fulfillmentTx) @@ -687,6 +674,7 @@ func TestVRFOwner(t *testing.T) { vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -696,8 +684,6 @@ func TestVRFOwner(t *testing.T) { vrfv2Config := config.VRFv2 cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -726,15 +712,14 @@ func TestVRFOwner(t *testing.T) { UseTestCoordinator: true, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") t.Run("Request Randomness With Force-Fulfill", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) consumers, subIDsForForceFulfill, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -825,6 +810,7 @@ func TestVRFV2WithBHS(t *testing.T) { subIDsForCancellingAfterTest []uint64 vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -834,8 +820,6 @@ func TestVRFV2WithBHS(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -868,7 +852,7 @@ func TestVRFV2WithBHS(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFV2 universe") t.Run("BHS Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { @@ -881,8 +865,7 @@ func TestVRFV2WithBHS(t *testing.T) { //Underfund Subscription configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForBHS, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -917,8 +900,6 @@ func TestVRFV2WithBHS(t *testing.T) { var wg sync.WaitGroup wg.Add(1) //Wait at least 256 blocks - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") _, err = actions.WaitForBlockNumberToBe( randRequestBlockNumber+uint64(257), sethClient, @@ -952,8 +933,7 @@ func TestVRFV2WithBHS(t *testing.T) { configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) consumers, subIDsForBHS, err := vrfv2.SetupNewConsumersAndSubs( - testEnv, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -988,9 +968,6 @@ func TestVRFV2WithBHS(t *testing.T) { _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") - sethClient, err := testEnv.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - var wg sync.WaitGroup wg.Add(1) _, err = actions.WaitForBlockNumberToBe( @@ -1051,6 +1028,7 @@ func TestVRFV2NodeReorg(t *testing.T) { subIDsForCancellingAfterTest []uint64 defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1063,8 +1041,6 @@ func TestVRFV2NodeReorg(t *testing.T) { } chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1106,15 +1082,11 @@ func TestVRFV2NodeReorg(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: chainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, _, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, _, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2 universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - env, - chainID, + sethClient, vrfContracts.CoordinatorV2, config, vrfContracts.LinkToken, @@ -1153,11 +1125,11 @@ func TestVRFV2NodeReorg(t *testing.T) { // rewind chain to block number after the request was made, but before the request was fulfilled rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //2. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) //3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made @@ -1202,11 +1174,11 @@ func TestVRFV2NodeReorg(t *testing.T) { // rewind chain to block number before the randomness request was made rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //3. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) //4. ensure that chain is reorged and latest block number is less than the block number when request was made @@ -1235,6 +1207,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1244,8 +1217,6 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1274,12 +1245,9 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2.SetupVRFV2Universe(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2 universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - //batchMaxGas := config.MaxGasLimit() (2.5 mill) + 400_000 = 2.9 mill //callback gas limit set by consumer = 500k // so 4 requests should be fulfilled inside 1 tx since 500k*4 < 2.9 mill @@ -1331,8 +1299,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfNode.Job = job consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - env, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, @@ -1453,8 +1420,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfNode.Job = job consumers, subIDs, err := vrfv2.SetupNewConsumersAndSubs( - env, - chainID, + sethClient, vrfContracts.CoordinatorV2, configCopy, vrfContracts.LinkToken, diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 52b5116a19..b888f56c1a 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/seth" + "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" @@ -44,6 +46,7 @@ func TestVRFv2Plus(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -53,9 +56,6 @@ func TestVRFv2Plus(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -84,19 +84,16 @@ func TestVRFv2Plus(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - t.Run("Link Billing", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) - isNativeBilling := false + var isNativeBilling = false + consumers, subIDsForRequestRandomness, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -154,9 +151,7 @@ func TestVRFv2Plus(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -212,8 +207,7 @@ func TestVRFv2Plus(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -253,11 +247,11 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("CL Node VRF Job Runs", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) - isNativeBilling := false + var isNativeBilling = false + consumers, subIDsForRequestRandomness, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -294,11 +288,11 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Direct Funding", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) + wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment( testcontext.Get(t), l, - env, - chainID, + sethClient, &configCopy, vrfContracts.LinkToken, vrfContracts.MockETHLINKFeed, @@ -409,10 +403,10 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Canceling Sub And Returning Funds", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) + _, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -514,8 +508,7 @@ func TestVRFv2Plus(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -659,10 +652,10 @@ func TestVRFv2Plus(t *testing.T) { }) t.Run("Owner Withdraw", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -749,6 +742,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -758,8 +752,6 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -788,7 +780,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") t.Run("Request Randomness with multiple sending keys", func(t *testing.T) { @@ -797,8 +789,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -831,8 +822,6 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { 0, ) require.NoError(t, err, "error requesting randomness and waiting for fulfilment") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") fulfillmentTx, _, err := sethClient.Client.TransactionByHash(testcontext.Get(t), randomWordsFulfilledEvent.Raw.TxHash) require.NoError(t, err, "error getting tx from hash") fulfillmentTxFromAddress, err := actions.GetTxFromAddress(fulfillmentTx) @@ -858,6 +847,7 @@ func TestVRFv2PlusMigration(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -867,8 +857,6 @@ func TestVRFv2PlusMigration(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -897,12 +885,9 @@ func TestVRFv2PlusMigration(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - // Migrate subscription from old coordinator to new coordinator, verify if balances // are moved correctly and requests can be made successfully in the subscription in // new coordinator @@ -911,8 +896,7 @@ func TestVRFv2PlusMigration(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1081,8 +1065,7 @@ func TestVRFv2PlusMigration(t *testing.T) { wrapperContracts, wrapperSubID, err := vrfv2plus.SetupVRFV2PlusWrapperEnvironment( testcontext.Get(t), l, - env, - chainID, + sethClient, &configCopy, vrfContracts.LinkToken, vrfContracts.MockETHLINKFeed, @@ -1258,6 +1241,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1267,8 +1251,6 @@ func TestVRFV2PlusWithBHS(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1301,13 +1283,10 @@ func TestVRFV2PlusWithBHS(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - - isNativeBilling := true + var isNativeBilling = true t.Run("BHS Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { if os.Getenv("TEST_UNSKIP") != "true" { t.Skip("Skipped due to long execution time. Should be run on-demand on live testnet with TEST_UNSKIP=\"true\".") @@ -1319,8 +1298,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1401,8 +1379,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1493,6 +1470,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1502,8 +1480,6 @@ func TestVRFV2PlusWithBHF(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1543,14 +1519,11 @@ func TestVRFV2PlusWithBHF(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: chainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse( + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse( testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err) - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - - isNativeBilling := true + var isNativeBilling = true t.Run("BHF Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { configCopy := config.MustCopy().(tc.TestConfig) // Underfund Subscription @@ -1559,8 +1532,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1655,6 +1627,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1664,8 +1637,6 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1700,7 +1671,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { config.VRFv2Plus.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) config.VRFv2Plus.General.SubscriptionFundingAmountNative = ptr.Ptr(float64(0)) - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") t.Run("Timed out request fulfilled after node restart with replay", func(t *testing.T) { @@ -1709,8 +1680,7 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -1826,6 +1796,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) vrfContracts *vrfcommon.VRFContracts subIDsForCancellingAfterTest []*big.Int vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1835,8 +1806,6 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1870,13 +1839,12 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) config.VRFv2Plus.General.MinimumConfirmations = ptr.Ptr[uint16](0) config.VRFv2Plus.General.VRFJobSimulationBlock = ptr.Ptr[string]("pending") - env, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, config, vrfContracts.LinkToken, @@ -1922,6 +1890,7 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { subIDsForCancellingAfterTest []*big.Int defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -1934,8 +1903,6 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { } chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -1976,18 +1943,13 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: chainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, _, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2Plus universe") var isNativeBilling = true - - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, config, vrfContracts.LinkToken, @@ -2022,11 +1984,11 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { // rewind chain to block number after the request was made, but before the request was fulfilled rewindChainToBlock := randomWordsRequestedEvent.Raw.BlockNumber + 1 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //2. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlock, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlock)) // 3.1 ensure that chain is reorged and latest block number is greater than the block number when request was made @@ -2070,11 +2032,11 @@ func TestVRFv2PlusNodeReorg(t *testing.T) { // rewind chain to block number before the randomness request was made rewindChainToBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - 3 - rpcUrl, err := actions.GetRPCUrl(env, chainID) + rpcUrl, err := vrfcommon.GetRPCUrl(env, chainID) require.NoError(t, err, "error getting rpc url") //3. rewind chain by n number of blocks - basically, mimicking reorg scenario - latestBlockNumberAfterReorg, err := actions.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) + latestBlockNumberAfterReorg, err := vrfcommon.RewindSimulatedChainToBlockNumber(testcontext.Get(t), sethClient, rpcUrl, rewindChainToBlockNumber, l) require.NoError(t, err, fmt.Sprintf("error rewinding chain to block number %d", rewindChainToBlockNumber)) // 4. ensure that chain is reorged and latest block number is less than the block number when request was made @@ -2104,6 +2066,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { defaultWalletAddress string vrfKey *vrfcommon.VRFKeyData nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + sethClient *seth.Client ) l := logging.GetTestLogger(t) @@ -2113,8 +2076,6 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { network := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0] chainID := network.ChainID cleanupFn := func() { - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") if sethClient.Cfg.IsSimulatedNetwork() { l.Info(). Str("Network Name", sethClient.Cfg.Network.Name). @@ -2143,12 +2104,9 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { UseTestCoordinator: false, ChainlinkNodeLogScannerSettings: test_env.DefaultChainlinkNodeLogScannerSettings, } - env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) + env, vrfContracts, vrfKey, nodeTypeToNodeMap, sethClient, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, vrfEnvConfig, newEnvConfig, l) require.NoError(t, err, "Error setting up VRFv2Plus universe") - sethClient, err := env.GetSethClient(chainID) - require.NoError(t, err, "Getting Seth client shouldn't fail") - //batchMaxGas := config.MaxGasLimit() (2.5 mill) + 400_000 = 2.9 mill //callback gas limit set by consumer = 500k // so 4 requests should be fulfilled inside 1 tx since 500k*4 < 2.9 mill @@ -2200,8 +2158,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -2315,8 +2272,7 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( testcontext.Get(t), - env, - chainID, + sethClient, vrfContracts.CoordinatorV2Plus, configCopy, vrfContracts.LinkToken, @@ -2382,5 +2338,4 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { // verify that all fulfillments should be in separate txs require.Equal(t, int(randRequestCount), len(singleFulfillmentTxs)) }) - } diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go index 401100748d..37837c666a 100644 --- a/integration-tests/soak/forwarder_ocr_test.go +++ b/integration-tests/soak/forwarder_ocr_test.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" ) @@ -25,14 +25,14 @@ ForwardersEnabled = true` config, err := tc.GetConfig("Soak", tc.OCR) require.NoError(t, err, "Error getting config") - ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, true) + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, testsetups.WithForwarderFlow(true)) require.NoError(t, err, "Error creating soak test") ocrSoakTest.DeployEnvironment(customNetworkTOML, &config) if ocrSoakTest.Environment().WillUseRemoteRunner() { return } t.Cleanup(func() { - if err := actions_seth.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { + if err := actions.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error tearing down environment") } }) diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index e99ecdf072..290cc00255 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -1,19 +1,27 @@ package soak import ( + "fmt" "testing" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" + "time" + + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" + "github.com/google/uuid" + "github.com/smartcontractkit/havoc/k8schaos" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" ) func TestOCRSoak(t *testing.T) { - l := logging.GetTestLogger(t) // Use this variable to pass in any custom EVM specific TOML values to your Chainlink nodes customNetworkTOML := `` // Uncomment below for debugging TOML issues on the node @@ -21,29 +29,185 @@ func TestOCRSoak(t *testing.T) { // fmt.Println("Using Chainlink TOML\n---------------------") // fmt.Println(networks.AddNetworkDetailedConfig(config.BaseOCR1Config, customNetworkTOML, network)) // fmt.Println("---------------------") - config, err := tc.GetConfig("Soak", tc.OCR) require.NoError(t, err, "Error getting config") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, customNetworkTOML) +} + +func TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled(t *testing.T) { + config, err := tc.GetConfig(t.Name(), tc.OCR) + require.NoError(t, err, "Error getting config") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, "") +} + +func TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled(t *testing.T) { + config, err := tc.GetConfig(t.Name(), tc.OCR) + require.NoError(t, err, "Error getting config") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, "") +} + +func TestOCRSoak_GasSpike(t *testing.T) { + config, err := tc.GetConfig(t.Name(), tc.OCR) + require.NoError(t, err, "Error getting config") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, "") +} + +// TestOCRSoak_ChangeBlockGasLimit changes next block gas limit and sets it to percentage of last gasUsed in previous block creating congestion +func TestOCRSoak_ChangeBlockGasLimit(t *testing.T) { + config, err := tc.GetConfig(t.Name(), tc.OCR) + require.NoError(t, err, "Error getting config") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, "") +} + +// TestOCRSoak_RPCDownForAllCLNodes simulates a network chaos by bringing down network to RPC node for all Chainlink Nodes +func TestOCRSoak_RPCDownForAllCLNodes(t *testing.T) { + config, err := tc.GetConfig(t.Name(), tc.OCR) + require.NoError(t, err, "Error getting config") + require.True(t, config.Network.IsSimulatedGethSelected(), "This test requires simulated geth") + + namespace := fmt.Sprintf("%s-%s", "soak-ocr-simulated-geth", uuid.NewString()[0:5]) + chaos, err := gethNetworkDownChaos(GethNetworkDownChaosOpts{ + DelayCreate: time.Minute * 2, + Duration: time.Minute * 5, + Name: "ocr-soak-test-geth-network-down-all-nodes", + Description: "Geth Network Down For All Chainlink Nodes", + Namespace: namespace, + TargetSelector: v1alpha1.PodSelector{ + Selector: v1alpha1.PodSelectorSpec{ + GenericSelectorSpec: v1alpha1.GenericSelectorSpec{ + Namespaces: []string{namespace}, + LabelSelectors: map[string]string{"app": "chainlink-0"}, + }, + }, + Mode: v1alpha1.AllMode, + }, + }) + require.NoError(t, err, "Error creating chaos") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, + testsetups.WithNamespace(namespace), + testsetups.WithChaos([]*k8schaos.Chaos{chaos}), + ) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, "") +} + +// TestOCRSoak_RPCDownForAllCLNodes simulates a network chaos by bringing down network to RPC node for 50% of Chainlink Nodes +func TestOCRSoak_RPCDownForHalfCLNodes(t *testing.T) { + config, err := tc.GetConfig(t.Name(), tc.OCR) + require.NoError(t, err, "Error getting config") + require.True(t, config.Network.IsSimulatedGethSelected(), "This test requires simulated geth") + + namespace := fmt.Sprintf("%s-%s", "soak-ocr-simulated-geth", uuid.NewString()[0:5]) + chaos, err := gethNetworkDownChaos(GethNetworkDownChaosOpts{ + DelayCreate: time.Minute * 2, + Duration: time.Minute * 5, + Name: "ocr-soak-test-geth-network-down-half-nodes", + Description: "Geth Network Down For 50 Percent Of Chainlink Nodes", + Namespace: namespace, + TargetSelector: v1alpha1.PodSelector{ + Selector: v1alpha1.PodSelectorSpec{ + GenericSelectorSpec: v1alpha1.GenericSelectorSpec{ + Namespaces: []string{namespace}, + LabelSelectors: map[string]string{"app": "chainlink-0"}, + }, + }, + Mode: v1alpha1.FixedPercentMode, + Value: "50", + }, + }) + require.NoError(t, err, "Error creating chaos") + ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, + testsetups.WithNamespace(namespace), + testsetups.WithChaos([]*k8schaos.Chaos{chaos}), + ) + require.NoError(t, err, "Error creating OCR soak test") + runOCRSoakTest(t, ocrSoakTest, config, "") +} - ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, false) - require.NoError(t, err, "Error creating soak test") - if !ocrSoakTest.Interrupted() { - ocrSoakTest.DeployEnvironment(customNetworkTOML, &config) +func runOCRSoakTest(t *testing.T, test *testsetups.OCRSoakTest, config tc.TestConfig, customNetworkTOML string) { + l := logging.GetTestLogger(t) + + l.Info().Str("test", t.Name()).Msg("Starting OCR soak test") + if !test.Interrupted() { + test.DeployEnvironment(customNetworkTOML, &config) } - if ocrSoakTest.Environment().WillUseRemoteRunner() { + if test.Environment().WillUseRemoteRunner() { return } t.Cleanup(func() { - if err := actions_seth.TeardownRemoteSuite(ocrSoakTest.TearDownVals(t)); err != nil { + if err := actions.TeardownRemoteSuite(test.TearDownVals(t)); err != nil { l.Error().Err(err).Msg("Error tearing down environment") } }) - if ocrSoakTest.Interrupted() { - err = ocrSoakTest.LoadState() + if test.Interrupted() { + err := test.LoadState() require.NoError(t, err, "Error loading state") - ocrSoakTest.Resume() + test.Resume() } else { - ocrSoakTest.Setup(&config) - ocrSoakTest.Run() + test.Setup(&config) + test.Run() } } + +type GethNetworkDownChaosOpts struct { + Name string + Namespace string + Description string + TargetSelector v1alpha1.PodSelector + DelayCreate time.Duration + Duration time.Duration +} + +func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*k8schaos.Chaos, error) { + k8sClient, err := k8schaos.NewChaosMeshClient() + if err != nil { + return nil, err + } + return k8schaos.NewChaos(k8schaos.ChaosOpts{ + Description: opts.Description, + DelayCreate: opts.DelayCreate, + Object: &v1alpha1.NetworkChaos{ + TypeMeta: metav1.TypeMeta{ + Kind: "NetworkChaos", + APIVersion: "chaos-mesh.org/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: opts.Name, + Namespace: opts.Namespace, + }, + Spec: v1alpha1.NetworkChaosSpec{ + Action: v1alpha1.LossAction, + PodSelector: v1alpha1.PodSelector{ + Mode: v1alpha1.AllMode, + Selector: v1alpha1.PodSelectorSpec{ + GenericSelectorSpec: v1alpha1.GenericSelectorSpec{ + Namespaces: []string{opts.Namespace}, + LabelSelectors: map[string]string{"app": "geth"}, + }, + }, + }, + Duration: ptr.Ptr(opts.Duration.String()), + Direction: v1alpha1.Both, + Target: &opts.TargetSelector, + TcParameter: v1alpha1.TcParameter{ + Loss: &v1alpha1.LossSpec{ + Loss: "100", + }, + }, + }, + }, + Client: k8sClient, + Logger: &k8schaos.Logger, + }) + +} diff --git a/integration-tests/testconfig/automation/example.toml b/integration-tests/testconfig/automation/example.toml index cc48749a15..3b48e89a54 100644 --- a/integration-tests/testconfig/automation/example.toml +++ b/integration-tests/testconfig/automation/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/forwarder_ocr/example.toml b/integration-tests/testconfig/forwarder_ocr/example.toml index 314c1b6781..0b762299af 100644 --- a/integration-tests/testconfig/forwarder_ocr/example.toml +++ b/integration-tests/testconfig/forwarder_ocr/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/forwarder_ocr2/example.toml b/integration-tests/testconfig/forwarder_ocr2/example.toml index 9f99284cc2..b3bc45d270 100644 --- a/integration-tests/testconfig/forwarder_ocr2/example.toml +++ b/integration-tests/testconfig/forwarder_ocr2/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/functions/example.toml b/integration-tests/testconfig/functions/example.toml index 77420ceaf3..7502a6fc44 100644 --- a/integration-tests/testconfig/functions/example.toml +++ b/integration-tests/testconfig/functions/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use simulated network diff --git a/integration-tests/testconfig/keeper/example.toml b/integration-tests/testconfig/keeper/example.toml index c9a5c829d3..5abb583562 100644 --- a/integration-tests/testconfig/keeper/example.toml +++ b/integration-tests/testconfig/keeper/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/log_poller/example.toml b/integration-tests/testconfig/log_poller/example.toml index 69d1263b94..c28d36ae12 100644 --- a/integration-tests/testconfig/log_poller/example.toml +++ b/integration-tests/testconfig/log_poller/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/log_poller/log_poller.toml b/integration-tests/testconfig/log_poller/log_poller.toml index 6b08805447..d2277d619a 100644 --- a/integration-tests/testconfig/log_poller/log_poller.toml +++ b/integration-tests/testconfig/log_poller/log_poller.toml @@ -180,3 +180,15 @@ FinalityTagEnabled = false [TestLogPollerReplayFixedDepth.LogPoller.General] use_finality_tag = false +[TestReorgAboveFinality_FinalityTagDisabled.NodeConfig] +CommonChainConfigTOML = """ +AutoCreateKey = true +MinContractPayment = 0 +LogPollInterval="500ms" +BackupLogPollerBlockDelay = 0 +FinalityDepth = 10 +FinalityTagEnabled = false +""" +[TestReorgAboveFinality_FinalityTagDisabled.PrivateEthereumNetwork] +ethereum_version = "eth1" +execution_layer = "geth" diff --git a/integration-tests/testconfig/node/example.toml b/integration-tests/testconfig/node/example.toml index e6777bc835..510379b4f0 100644 --- a/integration-tests/testconfig/node/example.toml +++ b/integration-tests/testconfig/node/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/ocr/example.toml b/integration-tests/testconfig/ocr/example.toml index 3f44956676..f9c6453bc5 100644 --- a/integration-tests/testconfig/ocr/example.toml +++ b/integration-tests/testconfig/ocr/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/ocr/ocr.toml b/integration-tests/testconfig/ocr/ocr.toml index 31224599d8..4e280e88f0 100644 --- a/integration-tests/testconfig/ocr/ocr.toml +++ b/integration-tests/testconfig/ocr/ocr.toml @@ -82,3 +82,115 @@ test_duration="15m" ocr_version="1" number_of_contracts=2 time_between_rounds="1m" + +# Soak test configuration with Geth reorg below finality with FinalityTagEnabled=false +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.NodeConfig] +CommonChainConfigTOML = """ +AutoCreateKey = true +MinContractPayment = 0 +LogPollInterval="500ms" +BackupLogPollerBlockDelay = 0 +FinalityDepth = 30 +FinalityTagEnabled = false +""" +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.Network] +selected_networks=["simulated"] +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.Network.GethReorgConfig] +enabled = true +depth = 15 +delay_create = "3s" +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.Common] +chainlink_node_funding = 0.5 +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.OCR] +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.OCR.Common] +test_duration="15m" +[TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" + +# Soak test configuration with Geth reorg below finality with FinalityTagEnabled=true +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.NodeConfig] +CommonChainConfigTOML = """ +AutoCreateKey = true +MinContractPayment = 0 +LogPollInterval="500ms" +BackupLogPollerBlockDelay = 0 +FinalityTagEnabled = true + +[HeadTracker] +HistoryDepth = 10 +""" +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.Network] +selected_networks=["simulated"] +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.Network.GethReorgConfig] +enabled = true +depth = 15 +delay_create = "3s" +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.Common] +chainlink_node_funding = 0.5 +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.OCR] +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.OCR.Common] +test_duration="15m" +[TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" + +# OCR soak test configuration with gas spike on Anvil network +[TestOCRSoak_GasSpike.Common] +chainlink_node_funding = 0.5 +[TestOCRSoak_GasSpike.OCR.Common] +test_duration="15m" +[TestOCRSoak_GasSpike.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" +[TestOCRSoak_GasSpike.Network] +selected_networks=["Anvil"] +[TestOCRSoak_GasSpike.Network.AnvilConfigs.anvil.GasSpikeSimulation] +enabled = true +start_gas_price = 2000000000 +gas_rise_percentage = 0.7 +gas_spike = true +delay_create = "1m" +duration = "3m" + +# OCR soak test configuration with change to gas limit on Anvil network +[TestOCRSoak_ChangeBlockGasLimit.Common] +chainlink_node_funding = 0.5 +[TestOCRSoak_ChangeBlockGasLimit.OCR.Common] +test_duration="15m" +[TestOCRSoak_ChangeBlockGasLimit.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" +[TestOCRSoak_ChangeBlockGasLimit.Network] +selected_networks=["Anvil"] +[TestOCRSoak_ChangeBlockGasLimit.Network.AnvilConfigs.anvil.GasLimitSimulation] +enabled = true +next_gas_limit_percentage = 0.5 +delay_create = "1m" +duration = "3m" + +[TestOCRSoak_RPCDownForAllCLNodes.Common] +chainlink_node_funding = 0.5 +[TestOCRSoak_RPCDownForAllCLNodes.OCR.Common] +test_duration="15m" +[TestOCRSoak_RPCDownForAllCLNodes.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" +[TestOCRSoak_RPCDownForAllCLNodes.Network] +selected_networks=["simulated"] + +[TestOCRSoak_RPCDownForHalfCLNodes.Common] +chainlink_node_funding = 0.5 +[TestOCRSoak_RPCDownForHalfCLNodes.OCR.Common] +test_duration="15m" +[TestOCRSoak_RPCDownForHalfCLNodes.OCR.Soak] +ocr_version="1" +number_of_contracts=2 +time_between_rounds="1m" +[TestOCRSoak_RPCDownForHalfCLNodes.Network] +selected_networks=["simulated"] \ No newline at end of file diff --git a/integration-tests/testconfig/ocr2/example.toml b/integration-tests/testconfig/ocr2/example.toml index 6e7138aeda..bdbd06d0a9 100644 --- a/integration-tests/testconfig/ocr2/example.toml +++ b/integration-tests/testconfig/ocr2/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 65e6221650..2b8bf0652b 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -13,7 +13,6 @@ import ( "github.com/google/uuid" "github.com/pelletier/go-toml/v2" "github.com/pkg/errors" - "github.com/rs/zerolog" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -280,15 +279,6 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { testConfig.ConfigurationName = configurationName logger.Debug().Msgf("Will apply configuration named '%s' if it is found in any of the configs", configurationName) - var handleSpecialOverrides = func(logger zerolog.Logger, filename, configurationName string, target *TestConfig, content []byte, product Product) error { - switch product { - case Automation: - return handleAutomationConfigOverride(logger, filename, configurationName, target, content) - default: - return handleDefaultConfigOverride(logger, filename, configurationName, target, content) - } - } - // read embedded configs is build tag "embed" is set // this makes our life much easier when using a binary if areConfigsEmbedded { @@ -303,34 +293,34 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { return TestConfig{}, errors.Wrapf(err, "error reading embedded config") } - err = handleSpecialOverrides(logger, fileName, configurationName, &testConfig, file, product) + err = ctf_config.BytesToAnyTomlStruct(logger, fileName, configurationName, &testConfig, file) if err != nil { return TestConfig{}, errors.Wrapf(err, "error unmarshalling embedded config") } } - } - - logger.Info().Msg("Reading configs from file system") - for _, fileName := range fileNames { - logger.Debug().Msgf("Looking for config file %s", fileName) - filePath, err := osutil.FindFile(fileName, osutil.DEFAULT_STOP_FILE_NAME, 3) + } else { + logger.Info().Msg("Reading configs from file system") + for _, fileName := range fileNames { + logger.Debug().Msgf("Looking for config file %s", fileName) + filePath, err := osutil.FindFile(fileName, osutil.DEFAULT_STOP_FILE_NAME, 3) - if err != nil && errors.Is(err, os.ErrNotExist) { - logger.Debug().Msgf("Config file %s not found", fileName) - continue - } else if err != nil { - return TestConfig{}, errors.Wrapf(err, "error looking for file %s", filePath) - } - logger.Debug().Str("location", filePath).Msgf("Found config file %s", fileName) + if err != nil && errors.Is(err, os.ErrNotExist) { + logger.Debug().Msgf("Config file %s not found", fileName) + continue + } else if err != nil { + return TestConfig{}, errors.Wrapf(err, "error looking for file %s", filePath) + } + logger.Debug().Str("location", filePath).Msgf("Found config file %s", fileName) - content, err := readFile(filePath) - if err != nil { - return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) - } + content, err := readFile(filePath) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + } - err = handleSpecialOverrides(logger, fileName, configurationName, &testConfig, content, product) - if err != nil { - return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + err = ctf_config.BytesToAnyTomlStruct(logger, fileName, configurationName, &testConfig, content) + if err != nil { + return TestConfig{}, errors.Wrapf(err, "error reading file %s", filePath) + } } } @@ -343,7 +333,7 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { return TestConfig{}, err } - err = handleSpecialOverrides(logger, Base64OverrideEnvVarName, configurationName, &testConfig, decoded, product) + err = ctf_config.BytesToAnyTomlStruct(logger, Base64OverrideEnvVarName, configurationName, &testConfig, decoded) if err != nil { return TestConfig{}, errors.Wrapf(err, "error unmarshaling base64 config") } @@ -351,7 +341,7 @@ func GetConfig(configurationName string, product Product) (TestConfig, error) { logger.Debug().Msg("Base64 config override from environment variable not found") } - // it neede some custom logic, so we do it separately + // it needs some custom logic, so we do it separately err := testConfig.readNetworkConfiguration() if err != nil { return TestConfig{}, errors.Wrapf(err, "error reading network config") @@ -571,76 +561,3 @@ func readFile(filePath string) ([]byte, error) { return content, nil } - -func handleAutomationConfigOverride(logger zerolog.Logger, filename, configurationName string, target *TestConfig, content []byte) error { - logger.Debug().Msgf("Handling automation config override for %s", filename) - oldConfig := MustCopy(target) - newConfig := TestConfig{} - - err := ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &target, content) - if err != nil { - return errors.Wrapf(err, "error reading file %s", filename) - } - - err = ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &newConfig, content) - if err != nil { - return errors.Wrapf(err, "error reading file %s", filename) - } - - // override instead of merging - if (newConfig.Automation != nil && len(newConfig.Automation.Load) > 0) && (oldConfig != nil && oldConfig.Automation != nil && len(oldConfig.Automation.Load) > 0) { - target.Automation.Load = newConfig.Automation.Load - } - - return nil -} - -func handleDefaultConfigOverride(logger zerolog.Logger, filename, configurationName string, target *TestConfig, content []byte) error { - logger.Debug().Msgf("Handling default config override for %s", filename) - oldConfig := MustCopy(target) - newConfig := TestConfig{} - - err := ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &target, content) - if err != nil { - return errors.Wrapf(err, "error reading file %s", filename) - } - - err = ctf_config.BytesToAnyTomlStruct(logger, filename, configurationName, &newConfig, content) - if err != nil { - return errors.Wrapf(err, "error reading file %s", filename) - } - - // temporary fix for Duration not being correctly copied - if oldConfig != nil && oldConfig.Seth != nil && oldConfig.Seth.Networks != nil { - for i, old_network := range oldConfig.Seth.Networks { - for _, target_network := range target.Seth.Networks { - if old_network.ChainID == target_network.ChainID { - oldConfig.Seth.Networks[i].TxnTimeout = target_network.TxnTimeout - } - } - } - } - - // override instead of merging - if (newConfig.Seth != nil && len(newConfig.Seth.Networks) > 0) && (oldConfig != nil && oldConfig.Seth != nil && len(oldConfig.Seth.Networks) > 0) { - networksToUse := map[string]*seth.Network{} - for i, old_network := range oldConfig.Seth.Networks { - for _, new_network := range newConfig.Seth.Networks { - if old_network.ChainID == new_network.ChainID { - oldConfig.Seth.Networks[i] = new_network - break - } - if _, ok := networksToUse[new_network.ChainID]; !ok { - networksToUse[new_network.ChainID] = new_network - } - } - networksToUse[old_network.ChainID] = oldConfig.Seth.Networks[i] - } - target.Seth.Networks = []*seth.Network{} - for _, network := range networksToUse { - target.Seth.Networks = append(target.Seth.Networks, network) - } - } - - return nil -} diff --git a/integration-tests/testconfig/vrfv2/example.toml b/integration-tests/testconfig/vrfv2/example.toml index 7b15597d59..9417a422cf 100644 --- a/integration-tests/testconfig/vrfv2/example.toml +++ b/integration-tests/testconfig/vrfv2/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testconfig/vrfv2plus/example.toml b/integration-tests/testconfig/vrfv2plus/example.toml index 7931b87908..d6e7a3f28d 100644 --- a/integration-tests/testconfig/vrfv2plus/example.toml +++ b/integration-tests/testconfig/vrfv2plus/example.toml @@ -31,6 +31,8 @@ bearer_token_secret="bearer_token" base_url="http://grafana.url" # url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" bearer_token_secret="my-awesome-token" # if you want to use polygon_mumbial diff --git a/integration-tests/testsetups/don_evm_chain.go b/integration-tests/testsetups/don_evm_chain.go deleted file mode 100644 index 3ade7f0d69..0000000000 --- a/integration-tests/testsetups/don_evm_chain.go +++ /dev/null @@ -1,81 +0,0 @@ -package testsetups - -import ( - "testing" - - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - e "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" -) - -type DonChain struct { - conf *DonChainConfig - EVMClient blockchain.EVMClient - EVMNetwork *blockchain.EVMNetwork - ContractDeployer contracts.ContractDeployer - LinkTokenContract contracts.LinkToken - ChainlinkNodes []*client.ChainlinkK8sClient - Mockserver *ctfClient.MockserverClient - l zerolog.Logger -} - -type DonChainConfig struct { - T *testing.T - Env *e.Environment - EVMNetwork *blockchain.EVMNetwork - EthereumProps *ethereum.Props - ChainlinkValues map[string]interface{} -} - -func NewDonChain(conf *DonChainConfig, logger zerolog.Logger) *DonChain { - return &DonChain{ - conf: conf, - EVMNetwork: conf.EVMNetwork, - l: logger, - } -} - -func (s *DonChain) Deploy() { - var err error - - s.conf.Env.AddHelm(mockservercfg.New(nil)). - AddHelm(mockserver.New(nil)). - AddHelm(ethereum.New(s.conf.EthereumProps)). - AddHelm(chainlink.New(0, s.conf.ChainlinkValues)) - - err = s.conf.Env.Run() - require.NoError(s.conf.T, err) - - s.initializeClients() -} - -func (s *DonChain) initializeClients() { - var err error - network := *s.conf.EVMNetwork - s.EVMClient, err = blockchain.NewEVMClient(network, s.conf.Env, s.l) - require.NoError(s.conf.T, err, "Connecting to blockchain nodes shouldn't fail") - - s.ContractDeployer, err = contracts.NewContractDeployer(s.EVMClient, s.l) - require.NoError(s.conf.T, err) - - s.ChainlinkNodes, err = client.ConnectChainlinkNodes(s.conf.Env) - require.NoError(s.conf.T, err, "Connecting to chainlink nodes shouldn't fail") - - s.Mockserver, err = ctfClient.ConnectMockServer(s.conf.Env) - require.NoError(s.conf.T, err, "Creating mockserver clients shouldn't fail") - - s.EVMClient.ParallelTransactions(true) - - s.LinkTokenContract, err = s.ContractDeployer.DeployLinkTokenContract() - require.NoError(s.conf.T, err, "Deploying Link Token Contract shouldn't fail") -} diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index 18c12d35c9..81f2ce0edf 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -33,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -195,7 +194,7 @@ func (k *KeeperBenchmarkTest) Setup(env *environment.Environment, config tt.Keep if inputs.RegistryVersions[index] == ethereum.RegistryVersion_2_0 || inputs.RegistryVersions[index] == ethereum.RegistryVersion_2_1 || inputs.RegistryVersions[index] == ethereum.RegistryVersion_2_2 { nodesToFund = k.chainlinkNodes[1:] } - err = actions_seth.FundChainlinkNodesAtKeyIndexFromRootAddress(k.log, k.chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(nodesToFund), k.Inputs.ChainlinkNodeFunding, index) + err = actions.FundChainlinkNodesAtKeyIndexFromRootAddress(k.log, k.chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(nodesToFund), k.Inputs.ChainlinkNodeFunding, index) require.NoError(k.t, err, "Funding Chainlink nodes shouldn't fail") } @@ -730,7 +729,7 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { registrar, err = contracts.DeployKeeperRegistrar(k.chainClient, registryVersion, k.linkToken.Address(), registrarSettings) require.NoError(k.t, err, "Funding keeper registrar contract shouldn't fail") } else { // OCR automation - v2.X - registry, registrar = actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar = actions.DeployAutoOCRRegistryAndRegistrar( k.t, k.chainClient, registryVersion, *k.Inputs.KeeperRegistrySettings, k.linkToken, ) @@ -799,10 +798,10 @@ func (k *KeeperBenchmarkTest) DeployBenchmarkKeeperContracts(index int) { linkFunds = big.NewInt(0).Add(linkFunds, minLinkBalance) - err = actions_seth.DeployMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds) + err = actions.DeployMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds) require.NoError(k.t, err, "Sending link funds to deployment addresses shouldn't fail") - upkeepIds := actions_seth.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false) + upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), registry, registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false) k.keeperRegistries[index] = registry k.keeperRegistrars[index] = registrar diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 2c3452b77d..f143ad2568 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -15,9 +15,13 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-testing-framework/grafana" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/google/uuid" "github.com/pelletier/go-toml/v2" "github.com/rs/zerolog" "github.com/smartcontractkit/seth" @@ -26,8 +30,10 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + "github.com/smartcontractkit/havoc/k8schaos" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" @@ -41,7 +47,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -71,7 +76,7 @@ type OCRSoakTest struct { log zerolog.Logger bootstrapNode *client.ChainlinkK8sClient workerNodes []*client.ChainlinkK8sClient - mockServer *ctfClient.MockserverClient + mockServer *ctf_client.MockserverClient filterQuery geth.FilterQuery ocrRoundStates []*testreporters.OCRRoundState @@ -83,14 +88,37 @@ type OCRSoakTest struct { ocrV2Instances []contracts.OffchainAggregatorV2 ocrV2InstanceMap map[string]contracts.OffchainAggregatorV2 // address : instance - rpcNetwork blockchain.EVMNetwork // network configuration for the blockchain node + 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 + gasLimitSimulationHappened bool // flag to indicate if a gas limit simulation happened during the test + chaosList []*k8schaos.Chaos // list of chaos simulations to run during the test +} + +type OCRSoakTestOption = func(c *OCRSoakTest) + +func WithChaos(chaosList []*k8schaos.Chaos) OCRSoakTestOption { + return func(c *OCRSoakTest) { + c.chaosList = chaosList + } +} + +func WithNamespace(ns string) OCRSoakTestOption { + return func(c *OCRSoakTest) { + c.namespace = ns + } +} + +func WithForwarderFlow(forwarderFlow bool) OCRSoakTestOption { + return func(c *OCRSoakTest) { + c.OperatorForwarderFlow = forwarderFlow + } } // NewOCRSoakTest creates a new OCR soak test to setup and run -func NewOCRSoakTest(t *testing.T, config *tc.TestConfig, forwarderFlow bool) (*OCRSoakTest, error) { +func NewOCRSoakTest(t *testing.T, config *tc.TestConfig, opts ...OCRSoakTestOption) (*OCRSoakTest, error) { test := &OCRSoakTest{ - Config: config, - OperatorForwarderFlow: forwarderFlow, + Config: config, TestReporter: testreporters.OCRSoakTestReporter{ OCRVersion: *config.OCR.Soak.OCRVersion, StartTime: time.Now(), @@ -103,22 +131,35 @@ func NewOCRSoakTest(t *testing.T, config *tc.TestConfig, forwarderFlow bool) (*O ocrV1InstanceMap: make(map[string]contracts.OffchainAggregator), ocrV2InstanceMap: make(map[string]contracts.OffchainAggregatorV2), } + for _, opt := range opts { + opt(test) + } + t.Cleanup(func() { + test.deleteChaosSimulations() + }) return test, test.ensureInputValues() } // DeployEnvironment deploys the test environment, starting all Chainlink nodes and other components for the test func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string, ocrTestConfig tt.OcrTestConfig) { nodeNetwork := networks.MustGetSelectedNetworkConfig(ocrTestConfig.GetNetworkConfig())[0] // Environment currently being used to soak test on - nsPre := fmt.Sprintf("soak-ocr-v%s-", *ocrTestConfig.GetOCRConfig().Soak.OCRVersion) - if o.OperatorForwarderFlow { - nsPre = fmt.Sprintf("%sforwarder-", nsPre) + + // Define namespace if default not set + if o.namespace == "" { + nsPre := fmt.Sprintf("soak-ocr-v%s-", *ocrTestConfig.GetOCRConfig().Soak.OCRVersion) + if o.OperatorForwarderFlow { + nsPre = fmt.Sprintf("%sforwarder-", nsPre) + } + + nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) + nsPre = strings.ReplaceAll(nsPre, "_", "-") + + o.namespace = fmt.Sprintf("%s-%s", nsPre, uuid.NewString()[0:5]) } - nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) - nsPre = strings.ReplaceAll(nsPre, "_", "-") baseEnvironmentConfig := &environment.Config{ TTL: time.Hour * 720, // 30 days, - NamespacePrefix: nsPre, + Namespace: o.namespace, Test: o.t, PreventPodEviction: true, } @@ -193,6 +234,12 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string, ocrTe o.testEnvironment = testEnv o.namespace = testEnv.Cfg.Namespace + // If the test is using the remote runner, we don't need to set the network URLs + // as the remote runner will handle that + if o.Environment().WillUseRemoteRunner() { + return + } + o.rpcNetwork = nodeNetwork if o.rpcNetwork.Simulated && o.rpcNetwork.Name == "Anvil" { if testEnv.Cfg.InsideK8s { @@ -201,6 +248,20 @@ func (o *OCRSoakTest) DeployEnvironment(customChainlinkNetworkTOML string, ocrTe } else { // Test is running locally, set forwarded URL of Anvil blockchain node o.rpcNetwork.URLs = []string{anvilChart.ForwardedWSURL} + o.rpcNetwork.HTTPURLs = []string{anvilChart.ForwardedHTTPURL} + } + } else if o.rpcNetwork.Simulated && o.rpcNetwork.Name == blockchain.SimulatedEVMNetwork.Name { + if testEnv.Cfg.InsideK8s { + // Test is running inside K8s + o.rpcNetwork.URLs = blockchain.SimulatedEVMNetwork.URLs + } else { + // Test is running locally, set forwarded URL of Geth blockchain node + wsURLs := o.testEnvironment.URLs[blockchain.SimulatedEVMNetwork.Name+"_internal"] + httpURLs := o.testEnvironment.URLs[blockchain.SimulatedEVMNetwork.Name+"_internal_http"] + require.NotEmpty(o.t, wsURLs, "Forwarded Geth URLs should not be empty") + require.NotEmpty(o.t, httpURLs, "Forwarded Geth URLs should not be empty") + o.rpcNetwork.URLs = wsURLs + o.rpcNetwork.HTTPURLs = httpURLs } } } @@ -211,14 +272,14 @@ func (o *OCRSoakTest) Environment() *environment.Environment { } func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { - seth, err := actions_seth.GetChainClient(o.Config, o.rpcNetwork) + seth, err := seth_utils.GetChainClient(o.Config, o.rpcNetwork) require.NoError(o.t, err, "Error creating seth client") o.seth = seth nodes, err := client.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, err = ctfClient.ConnectMockServer(o.testEnvironment) + o.mockServer, err = ctf_client.ConnectMockServer(o.testEnvironment) require.NoError(o.t, err, "Creating mockserver clients shouldn't fail") linkContract, err := contracts.DeployLinkTokenContract(o.log, seth) @@ -226,14 +287,14 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { // Fund Chainlink nodes, excluding the bootstrap node o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") - err = actions_seth.FundChainlinkNodesFromRootAddress(o.log, seth, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) + err = actions.FundChainlinkNodesFromRootAddress(o.log, seth, 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_seth.DeployForwarderContracts( + 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") @@ -241,15 +302,15 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { 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_seth.AcceptAuthorizedReceiversOperator( + 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_seth.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) + actions.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) } } else if *ocrTestConfig.GetOCRConfig().Soak.OCRVersion == "1" { if o.OperatorForwarderFlow { - o.ocrV1Instances, err = actions_seth.DeployOCRContractsForwarderFlow( + o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( o.log, o.seth, *o.Config.OCR.Soak.NumberOfContracts, @@ -259,7 +320,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { ) require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") } else { - o.ocrV1Instances, err = actions_seth.DeployOCRv1Contracts( + o.ocrV1Instances, err = actions.DeployOCRv1Contracts( o.log, seth, *o.Config.OCR.Soak.NumberOfContracts, @@ -284,7 +345,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { } ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - o.ocrV2Instances, err = actions_seth.DeployOCRv2Contracts( + o.ocrV2Instances, err = actions.DeployOCRv2Contracts( o.log, o.seth, *ocrTestConfig.GetOCRConfig().Soak.NumberOfContracts, @@ -295,7 +356,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { require.NoError(o.t, err, "Error deploying OCRv2 contracts") contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) require.NoError(o.t, err, "Error building median config") - err = actions_seth.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) + err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") } @@ -379,6 +440,7 @@ type OCRSoakTestState struct { BootStrapNodeURL string `toml:"bootstrapNodeURL"` WorkerNodeURLs []string `toml:"workerNodeURLs"` ChainURL string `toml:"chainURL"` + ReorgHappened bool `toml:"reorgHappened"` MockServerURL string `toml:"mockServerURL"` } @@ -404,6 +466,7 @@ func (o *OCRSoakTest) SaveState() error { MockServerURL: "http://mockserver:1080", // TODO: Make this dynamic BootStrapNodeURL: o.bootstrapNode.URL(), WorkerNodeURLs: workerNodeURLs, + ReorgHappened: o.reorgHappened, } data, err := toml.Marshal(testState) if err != nil { @@ -454,6 +517,7 @@ func (o *OCRSoakTest) LoadState() error { o.timeLeft = testState.TestDuration - testState.TimeRunning o.startTime = testState.StartTime o.startingBlockNum = testState.StartingBlockNum + o.reorgHappened = testState.ReorgHappened o.Config.OCR.Soak.OCRVersion = &testState.OCRVersion o.bootstrapNode, err = client.ConnectChainlinkNodeURL(testState.BootStrapNodeURL) @@ -485,7 +549,7 @@ func (o *OCRSoakTest) LoadState() error { } } - o.mockServer, err = ctfClient.ConnectMockServerURL(testState.MockServerURL) + o.mockServer, err = ctf_client.ConnectMockServerURL(testState.MockServerURL) if err != nil { return err } @@ -562,6 +626,77 @@ func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) { err := o.observeOCREvents() require.NoError(o.t, err, "Error subscribing to OCR events") + n := o.Config.GetNetworkConfig() + + // Schedule blockchain re-org if needed + // Reorg only avaible for Simulated Geth + if n.IsSimulatedGethSelected() && n.GethReorgConfig.Enabled { + var reorgDelay time.Duration + if n.GethReorgConfig.DelayCreate.Duration > testDuration { + // This may happen when test is resumed and the reorg delay is longer than the time left + o.log.Warn().Msg("Reorg delay is longer than test duration, reorg scheduled immediately") + reorgDelay = 0 + } else { + reorgDelay = n.GethReorgConfig.DelayCreate.Duration + } + time.AfterFunc(reorgDelay, func() { + if !o.reorgHappened { + o.startGethBlockchainReorg(o.rpcNetwork, n.GethReorgConfig) + } + }) + } + + // Schedule gas simulations if needed + // Gas simulation only available for Anvil + if o.rpcNetwork.Name == "Anvil" { + ac := o.Config.GetNetworkConfig().AnvilConfigs["ANVIL"] + if ac != nil && ac.GasSpikeSimulation.Enabled { + var delay time.Duration + if ac.GasSpikeSimulation.DelayCreate.Duration > testDuration { + // This may happen when test is resumed and the reorg delay is longer than the time left + o.log.Warn().Msg("Gas spike simulation delay is longer than test duration, gas simulation scheduled immediately") + delay = 0 + } else { + delay = ac.GasSpikeSimulation.DelayCreate.Duration + } + time.AfterFunc(delay, func() { + if !o.gasSpikeSimulationHappened { + o.startAnvilGasSpikeSimulation(o.rpcNetwork, ac.GasSpikeSimulation) + } + }) + } + if ac != nil && ac.GasLimitSimulation.Enabled { + var delay time.Duration + if ac.GasLimitSimulation.DelayCreate.Duration > testDuration { + // This may happen when test is resumed and the reorg delay is longer than the time left + o.log.Warn().Msg("Gas limit simulation delay is longer than test duration, gas simulation scheduled immediately") + delay = 0 + } else { + delay = ac.GasLimitSimulation.DelayCreate.Duration + } + time.AfterFunc(delay, func() { + if !o.gasLimitSimulationHappened { + o.startAnvilGasLimitSimulation(o.rpcNetwork, ac.GasLimitSimulation) + } + }) + } + } + + // Schedule chaos simulations if needed + if len(o.chaosList) > 0 { + for _, chaos := range o.chaosList { + chaos.Create(context.Background()) + chaos.AddListener(k8schaos.NewChaosLogger(o.log)) + chaos.AddListener(ocrTestChaosListener{t: o.t}) + // Add Grafana annotation if configured + if o.Config.Logging.Grafana != nil && o.Config.Logging.Grafana.BaseUrl != nil && o.Config.Logging.Grafana.BearerToken != nil && o.Config.Logging.Grafana.DashboardUID != nil { + chaos.AddListener(k8schaos.NewSingleLineGrafanaAnnotator(*o.Config.Logging.Grafana.BaseUrl, *o.Config.Logging.Grafana.BearerToken, *o.Config.Logging.Grafana.DashboardUID, o.log)) + } else { + o.log.Warn().Msg("Skipping Grafana annotation for chaos simulation. Grafana config is missing either BearerToken, BaseUrl or DashboardUID") + } + } + } + for { select { case <-interruption: @@ -575,6 +710,7 @@ func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) { o.log.Error().Err(err).Msg("Error saving state") } o.log.Warn().Str("Time Taken", time.Since(saveStart).String()).Msg("Saved state") + o.deleteChaosSimulations() os.Exit(interruptedExitCode) // Exit with interrupted code to indicate test was interrupted, not just a normal failure case <-endTest: return @@ -610,6 +746,71 @@ func (o *OCRSoakTest) complete() { o.TestReporter.RecordEvents(o.ocrRoundStates, o.testIssues) } +func (o *OCRSoakTest) startGethBlockchainReorg(network blockchain.EVMNetwork, conf ctf_config.ReorgConfig) { + client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + o.log.Info(). + Str("URL", client.URL). + Int("Depth", conf.Depth). + Msg("Starting blockchain reorg on Simulated Geth chain") + o.postGrafanaAnnotation(fmt.Sprintf("Starting blockchain reorg on Simulated Geth chain with depth %d", conf.Depth), nil) + err := client.GethSetHead(conf.Depth) + require.NoError(o.t, err, "Error starting blockchain reorg on Simulated Geth chain") + o.reorgHappened = true +} + +func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork, conf ctf_config.GasSpikeSimulationConfig) { + client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + o.log.Info(). + Str("URL", client.URL). + Any("GasSpikeSimulationConfig", conf). + Msg("Starting gas spike simulation on Anvil chain") + o.postGrafanaAnnotation(fmt.Sprintf("Starting gas spike simulation on Anvil chain. Config: %+v", conf), nil) + err := client.ModulateBaseFeeOverDuration(o.log, conf.StartGasPrice, conf.GasRisePercentage, conf.Duration.Duration, conf.GasSpike) + o.postGrafanaAnnotation(fmt.Sprintf("Gas spike simulation ended. Config: %+v", conf), nil) + require.NoError(o.t, err, "Error starting gas simulation on Anvil chain") + o.gasSpikeSimulationHappened = true +} + +func (o *OCRSoakTest) startAnvilGasLimitSimulation(network blockchain.EVMNetwork, conf ctf_config.GasLimitSimulationConfig) { + client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + latestBlock, err := o.seth.Client.BlockByNumber(context.Background(), nil) + require.NoError(o.t, err) + newGasLimit := int64(math.Ceil(float64(latestBlock.GasUsed()) * conf.NextGasLimitPercentage)) + o.log.Info(). + Str("URL", client.URL). + Any("GasLimitSimulationConfig", conf). + Uint64("LatestBlock", latestBlock.Number().Uint64()). + Uint64("LatestGasUsed", latestBlock.GasUsed()). + Uint64("LatestGasLimit", latestBlock.GasLimit()). + Int64("NewGasLimit", newGasLimit). + Msg("Starting gas limit simulation on Anvil chain") + o.postGrafanaAnnotation(fmt.Sprintf("Starting gas limit simulation on Anvil chain. Config: %+v", conf), nil) + err = client.AnvilSetBlockGasLimit([]interface{}{newGasLimit}) + require.NoError(o.t, err, "Error starting gas simulation on Anvil chain") + time.Sleep(conf.Duration.Duration) + o.log.Info(). + Str("URL", client.URL). + Any("GasLimitSimulationConfig", conf). + Uint64("LatestGasLimit", latestBlock.GasLimit()). + Msg("Returning to old gas limit simulation on Anvil chain") + o.postGrafanaAnnotation(fmt.Sprintf("Returning to old gas limit simulation on Anvil chain. Config: %+v", conf), nil) + err = client.AnvilSetBlockGasLimit([]interface{}{latestBlock.GasLimit()}) + require.NoError(o.t, err, "Error starting gas simulation on Anvil chain") + o.gasLimitSimulationHappened = true +} + +// Delete k8s chaos objects it any of them still exist +// This is needed to clean up the chaos objects if the test is interrupted or it finishes +func (o *OCRSoakTest) deleteChaosSimulations() { + for _, chaos := range o.chaosList { + err := chaos.Delete(context.Background()) + // Check if the error is because the chaos object is already deleted + if err != nil && !strings.Contains(err.Error(), "not found") { + o.log.Error().Err(err).Msg("Error deleting chaos object") + } + } +} + // setFilterQuery to look for all events that happened func (o *OCRSoakTest) setFilterQuery() { ocrAddresses := o.getContractAddresses() @@ -878,3 +1079,58 @@ func (o *OCRSoakTest) getContractAddresses() []common.Address { return contractAddresses } + +func (o *OCRSoakTest) postGrafanaAnnotation(text string, tags []string) { + var grafanaClient *grafana.Client + var dashboardUID *string + if o.Config.Logging.Grafana != nil { + baseURL := o.Config.Logging.Grafana.BaseUrl + dashboardUID = o.Config.Logging.Grafana.DashboardUID + token := o.Config.Logging.Grafana.BearerToken + if token == nil || baseURL == nil || dashboardUID == nil { + o.log.Warn().Msg("Skipping Grafana annotation. Grafana config is missing either BearerToken, BaseUrl or DashboardUID") + return + } + grafanaClient = grafana.NewGrafanaClient(*baseURL, *token) + } + _, _, err := grafanaClient.PostAnnotation(grafana.PostAnnotation{ + DashboardUID: *dashboardUID, + Tags: tags, + Text: fmt.Sprintf("Test Namespace: %s
%s
", o.namespace, text), + }) + if err != nil { + o.log.Error().Err(err).Msg("Error posting annotation to Grafana") + } else { + o.log.Info().Msgf("Annotated Grafana dashboard with text: %s", text) + } +} + +type ocrTestChaosListener struct { + t *testing.T +} + +func (l ocrTestChaosListener) OnChaosCreated(_ k8schaos.Chaos) { +} + +func (l ocrTestChaosListener) OnChaosCreationFailed(chaos k8schaos.Chaos, reason error) { + // Fail the test if chaos creation fails during chaos simulation + require.FailNow(l.t, "Error creating chaos simulation", reason.Error(), chaos) +} + +func (l ocrTestChaosListener) OnChaosStarted(_ k8schaos.Chaos) { +} + +func (l ocrTestChaosListener) OnChaosPaused(_ k8schaos.Chaos) { +} + +func (l ocrTestChaosListener) OnChaosEnded(_ k8schaos.Chaos) { +} + +func (l ocrTestChaosListener) OnChaosStatusUnknown(_ k8schaos.Chaos) { +} + +func (l ocrTestChaosListener) OnScheduleCreated(_ k8schaos.Schedule) { +} + +func (l ocrTestChaosListener) OnScheduleDeleted(_ k8schaos.Schedule) { +} diff --git a/integration-tests/testsetups/profile.go b/integration-tests/testsetups/profile.go deleted file mode 100644 index 14fe3d29ae..0000000000 --- a/integration-tests/testsetups/profile.go +++ /dev/null @@ -1,76 +0,0 @@ -package testsetups - -//revive:disable:dot-imports -import ( - "time" - - . "github.com/onsi/gomega" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - - "github.com/smartcontractkit/chainlink/integration-tests/client" - "github.com/smartcontractkit/chainlink/integration-tests/testreporters" -) - -// ChainlinkProfileTest runs a piece of code on Chainlink nodes with PPROF enabled, then downloads the PPROF results -type ChainlinkProfileTest struct { - Inputs ChainlinkProfileTestInputs - TestReporter testreporters.ChainlinkProfileTestReporter - env *environment.Environment - c blockchain.EVMClient -} - -// ChainlinkProfileTestInputs are the inputs necessary to run a profiling tests -type ChainlinkProfileTestInputs struct { - ProfileFunction func(*client.ChainlinkClient) - ProfileDuration time.Duration - ChainlinkNodes []*client.ChainlinkK8sClient -} - -// NewChainlinkProfileTest prepares a new keeper Chainlink profiling test to be run -func NewChainlinkProfileTest(inputs ChainlinkProfileTestInputs) *ChainlinkProfileTest { - return &ChainlinkProfileTest{ - Inputs: inputs, - } -} - -// Setup prepares contracts for the test -func (c *ChainlinkProfileTest) Setup(env *environment.Environment) { - c.ensureInputValues() - c.env = env -} - -// Run runs the profiling test -func (c *ChainlinkProfileTest) Run() { - profileGroup := new(errgroup.Group) - for ni, cl := range c.Inputs.ChainlinkNodes { - chainlinkNode := cl - nodeIndex := ni - profileGroup.Go(func() error { - profileResults, err := chainlinkNode.Profile(c.Inputs.ProfileDuration, c.Inputs.ProfileFunction) - profileResults.NodeIndex = nodeIndex - if err != nil { - return err - } - c.TestReporter.Results = append(c.TestReporter.Results, profileResults) - return nil - }) - } - Expect(profileGroup.Wait()).ShouldNot(HaveOccurred(), "Error while gathering chainlink Profile tests") -} - -// Networks returns the networks that the test is running on -func (c *ChainlinkProfileTest) TearDownVals() (*environment.Environment, []*client.ChainlinkK8sClient, reportModel.TestReporter, blockchain.EVMClient) { - return c.env, c.Inputs.ChainlinkNodes, &c.TestReporter, c.c -} - -// ensureValues ensures that all values needed to run the test are present -func (c *ChainlinkProfileTest) ensureInputValues() { - Expect(c.Inputs.ProfileFunction).ShouldNot(BeNil(), "Forgot to provide a function to profile") - Expect(c.Inputs.ProfileDuration.Seconds()).Should(BeNumerically(">=", 1), "Time to profile should be at least 1 second") - Expect(c.Inputs.ChainlinkNodes).ShouldNot(BeNil(), "Chainlink nodes you want to profile should be provided") - Expect(len(c.Inputs.ChainlinkNodes)).Should(BeNumerically(">", 0), "No Chainlink nodes provided to profile") -} diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 9de11c439c..7bedef393d 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -13,6 +13,8 @@ import ( "testing" "time" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -31,7 +33,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink/integration-tests/actions" - actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -981,7 +982,7 @@ type ChaosPauseData struct { } // ExecuteChaosExperiment executes the configured chaos experiment, which consist of pausing CL node or Postgres containers -func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, testConfig *tc.TestConfig, errorCh chan error) { +func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv, sethClient *seth.Client, testConfig *tc.TestConfig, errorCh chan error) { if testConfig == nil || testConfig.LogPoller.ChaosConfig == nil || *testConfig.LogPoller.ChaosConfig.ExperimentCount == 0 { errorCh <- nil return @@ -990,12 +991,6 @@ func ExecuteChaosExperiment(l zerolog.Logger, testEnv *test_env.CLClusterTestEnv chaosChan := make(chan ChaosPauseData, *testConfig.LogPoller.ChaosConfig.ExperimentCount) wg := &sync.WaitGroup{} - selectedNetwork := networks.MustGetSelectedNetworkConfig(testConfig.Network)[0] - sethClient, err := testEnv.GetSethClient(selectedNetwork.ChainID) - if err != nil { - errorCh <- err - } - go func() { // if we wanted to have more than 1 container paused, we'd need to make sure we aren't trying to pause an already paused one guardChan := make(chan struct{}, 1) @@ -1119,37 +1114,26 @@ func SetupLogPollerTestDocker( WithTestInstance(t). WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(clNodesCount). - WithFunding(big.NewFloat(chainlinkNodeFunding)). WithEVMNetworkOptions(evmNetworkExtraSettingsFn). WithChainlinkNodeLogScanner(logScannerSettings). WithStandardCleanup(). - WithSeth(). Build() require.NoError(t, err, "Error deploying test environment") - selectedNetwork := networks.MustGetSelectedNetworkConfig(testConfig.Network)[0] - chainClient, err := env.GetSethClient(selectedNetwork.ChainID) + evmNetwork, err := env.GetFirstEvmNetwork() + require.NoError(t, err, "Error getting first evm network") + + chainClient, err := seth_utils.GetChainClient(testConfig, *evmNetwork) require.NoError(t, err, "Error getting seth client") + err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(chainlinkNodeFunding)) + require.NoError(t, err, "Failed to fund the nodes") + nodeClients := env.ClCluster.NodeAPIs() workerNodes := nodeClients[1:] - var linkToken contracts.LinkToken - - switch network.ChainID { - // Simulated - case 1337: - linkToken, err = contracts.DeployLinkTokenContract(l, chainClient) - // Ethereum Sepolia - case 11155111: - linkToken, err = env.ContractLoader.LoadLINKToken("0x779877A7B0D9E8603169DdbD7836e478b4624789") - // Polygon Mumbai - case 80001: - linkToken, err = env.ContractLoader.LoadLINKToken("0x326C977E6efc84E512bB9C30f76E30c160eD06FB") - default: - panic("Not implemented") - } - require.NoError(t, err, "Error loading/deploying LINK token") + linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) + require.NoError(t, err, "Error deploying LINK token") linkBalance, err := linkToken.BalanceOf(context.Background(), chainClient.MustGetRootKeyAddress().Hex()) require.NoError(t, err, "Error getting LINK balance") @@ -1161,7 +1145,7 @@ func SetupLogPollerTestDocker( require.FailNowf(t, "Not enough LINK", "Not enough LINK to run the test. Need at least %s. but has only %s", big.NewInt(0).Div(minLinkBalance, big.NewInt(1e18)).String(), big.NewInt(0).Div(linkBalance, big.NewInt(1e18)).String()) } - registry, registrar := actions_seth.DeployAutoOCRRegistryAndRegistrar( + registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( t, chainClient, registryVersion, diff --git a/operator_ui/README.md b/operator_ui/README.md index 07bda2cd1d..ccb5173631 100644 --- a/operator_ui/README.md +++ b/operator_ui/README.md @@ -12,7 +12,12 @@ This package is responsible for rendering the UI of the chainlink node, which al ### Requirements -The `install.sh` script handles installing the specified tag of operator UI within the [tag file](./TAG). When executed, it downloads then moves the static assets of operator UI into the `core/web/assets` path. Then, when the chainlink binary is built, these assets are included into the build that gets served. +The `install.go` script handles installing the specified tag of operator UI within the [tag file](./TAG). When executed, it downloads then moves the static assets of operator UI into the `core/web/assets` path. Then, when the chainlink binary is built, these assets are included into the build that gets served. + +```sh +# The argument is the path from the this directory to the root of the repository +go run ./install.go .. +``` ## Updates diff --git a/operator_ui/TAG b/operator_ui/TAG index d6b3cc6c88..57ed352173 100644 --- a/operator_ui/TAG +++ b/operator_ui/TAG @@ -1 +1 @@ -v0.8.0-9f29991 +v0.8.0-7e6a14f diff --git a/operator_ui/install.go b/operator_ui/install.go new file mode 100644 index 0000000000..1e09783db6 --- /dev/null +++ b/operator_ui/install.go @@ -0,0 +1,162 @@ +package main + +import ( + "archive/tar" + "compress/gzip" + "context" + "fmt" + "io" + "log" + "net/http" + "os" + "path" + "path/filepath" + "strings" + "time" +) + +func main() { + const ( + owner = "smartcontractkit" + repo = "operator-ui" + fullRepo = owner + "/" + repo + tagPath = "operator_ui/TAG" + unpackDir = "core/web/assets" + downloadTimeoutSeconds = 10 + ) + // Grab first argument as root directory + if len(os.Args) < 2 { + log.Fatalln("Usage: install.go ") + } + rootDir := os.Args[1] + + tag := mustReadTagFile(path.Join(rootDir, tagPath)) + strippedTag := stripVersionFromTag(tag) + assetName := fmt.Sprintf("%s-%s-%s.tgz", owner, repo, strippedTag) + downloadUrl := fmt.Sprintf("https://github.com/%s/releases/download/%s/%s", fullRepo, tag, assetName) + + // Assuming that we're in "root/operator_ui/" + unpackPath := filepath.Join(rootDir, unpackDir) + err := rmrf(unpackPath) + if err != nil { + log.Fatalln(err) + } + + subPath := "package/artifacts/" + mustDownloadSubAsset(downloadUrl, downloadTimeoutSeconds, unpackPath, subPath) +} + +func mustReadTagFile(file string) string { + tagBytes, err := os.ReadFile(file) + if err != nil { + log.Fatalln(err) + } + tag := string(tagBytes) + return strings.TrimSpace(tag) +} + +func stripVersionFromTag(tag string) string { + return strings.TrimPrefix(tag, "v") +} + +func rmrf(path string) error { + err := os.RemoveAll(path) + if err != nil { + return err + } + + err = os.Mkdir(path, 0755) + return err +} + +// Download a sub asset from a .tgz file and extract it to a destination path +func mustDownloadSubAsset(downloadUrl string, downloadTimeoutSeconds int, unpackPath string, subPath string) { + fmt.Println("Downloading", downloadUrl) + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(downloadTimeoutSeconds)*time.Second) + defer cancel() + /* #nosec G107 */ + req, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadUrl, nil) + if err != nil { + log.Fatalln(err) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Fatalln(err) + } + + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + log.Fatalln(fmt.Errorf("failed to fetch asset: %s", resp.Status)) + } + + err = decompressTgzSubpath(resp.Body, unpackPath, subPath) + if err != nil { + log.Fatalln(err) + } +} + +// Decompress a .tgz file to a destination path, only extracting files that are in the subpath +// +// Subpath files are extracted to the root of the destination path, rather than preserving the subpath +func decompressTgzSubpath(file io.Reader, destPath string, subPath string) error { + // Create a gzip reader + gzr, err := gzip.NewReader(file) + if err != nil { + return fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gzr.Close() + + // Create a tar reader + tr := tar.NewReader(gzr) + + // Iterate through the files in the tar archive + for { + header, err := tr.Next() + switch { + case err == io.EOF: + return nil // End of tar archive + case err != nil: + return fmt.Errorf("failed to read tar file: %w", err) + case header == nil: + continue + } + // skip files that arent in the subpath + if !strings.HasPrefix(header.Name, subPath) { + continue + } + + // Strip the subpath from the header name + header.Name = strings.TrimPrefix(header.Name, subPath) + + // Target location where the dir/file should be created + target := fmt.Sprintf("%s/%s", destPath, header.Name) + + // Check the file type + switch header.Typeflag { + case tar.TypeDir: // Directory + if err := os.MkdirAll(target, 0755); err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + fmt.Println("Creating directory", target) + case tar.TypeReg: // Regular file + if err := writeFile(target, header, tr); err != nil { + return err + } + } + } +} + +func writeFile(target string, header *tar.Header, tr *tar.Reader) error { + /* #nosec G110 */ + f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) + if err != nil { + return fmt.Errorf("failed to open file: %w", err) + } + defer f.Close() + + if _, err := io.Copy(f, tr); err != nil { + return fmt.Errorf("failed to write file: %w", err) + } + fmt.Println("Creating file", target) + return nil +} diff --git a/operator_ui/install.sh b/operator_ui/install.sh deleted file mode 100755 index f86c9a2f35..0000000000 --- a/operator_ui/install.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -set -e - -owner=smartcontractkit -repo=operator-ui -fullRepo=${owner}/${repo} -gitRoot="$(dirname -- "$0")/../" -cd "$gitRoot/operator_ui" -unpack_dir="$gitRoot/core/web/assets" -tag=$(cat TAG) -# Remove the version prefix "v" -strippedTag="${tag:1}" -# Taken from https://github.com/kennyp/asdf-golang/blob/master/lib/helpers.sh -msg() { - echo -e "\033[32m$1\033[39m" >&2 -} - -err() { - echo -e "\033[31m$1\033[39m" >&2 -} - -fail() { - err "$1" - exit 1 -} - -msg "Getting release $tag for $fullRepo" -# https://docs.github.com/en/rest/releases/releases#get-a-release-by-tag-name -asset_name=${owner}-${repo}-${strippedTag}.tgz -download_url=https://github.com/${fullRepo}/releases/download/${tag}/${asset_name} - -# Inspired from https://github.com/kennyp/asdf-golang/blob/master/bin/download#L29 -msg "Download URL: ${download_url}" -# Check if we're able to download first -http_code=$(curl -LIs -w '%{http_code}' -o /dev/null "$download_url") -if [ "$http_code" -eq 404 ] || [ "$http_code" -eq 403 ]; then - fail "URL: ${download_url} returned status ${http_code}" -fi -# Then go ahead if we get a success code -msg "Downloading ${fullRepo}:${tag} asset: $asset_name..." -msg "" -curl -L -o "$asset_name" "$download_url" - -msg "Unpacking asset $asset_name" -tar -xvzf "$asset_name" - -msg "" -msg "Removing old contents of $unpack_dir" -rm -rf "$unpack_dir" -msg "Copying contents of package/artifacts to $unpack_dir" -cp -rf package/artifacts/. "$unpack_dir" || true - -msg "Cleaning up" -rm -r package -rm "$asset_name" diff --git a/package.json b/package.json index e4b3b564b9..ea42db5bae 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,10 @@ "url": "https://github.com/smartcontractkit/ccip/issues" }, "homepage": "https://github.com/smartcontractkit/ccip#readme", + "engines": { + "node": ">=18", + "pnpm": ">=9" + }, "devDependencies": { "@changesets/changelog-github": "^0.4.8", "@changesets/cli": "~2.26.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e3eb48674e..2eb9f6c0aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true @@ -20,37 +20,1037 @@ devDependencies: packages: - /@babel/code-frame@7.23.5: + '@babel/code-frame@7.23.5': resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.22.20': + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.23.4': + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.23.9': + resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} + engines: {node: '>=6.9.0'} + + '@changesets/apply-release-plan@6.1.4': + resolution: {integrity: sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==} + + '@changesets/assemble-release-plan@5.2.4': + resolution: {integrity: sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==} + + '@changesets/changelog-git@0.1.14': + resolution: {integrity: sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==} + + '@changesets/changelog-github@0.4.8': + resolution: {integrity: sha512-jR1DHibkMAb5v/8ym77E4AMNWZKB5NPzw5a5Wtqm1JepAuIF+hrKp2u04NKM14oBZhHglkCfrla9uq8ORnK/dw==} + + '@changesets/cli@2.26.2': + resolution: {integrity: sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==} + hasBin: true + + '@changesets/config@2.3.1': + resolution: {integrity: sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==} + + '@changesets/errors@0.1.4': + resolution: {integrity: sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==} + + '@changesets/get-dependents-graph@1.3.6': + resolution: {integrity: sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==} + + '@changesets/get-github-info@0.5.2': + resolution: {integrity: sha512-JppheLu7S114aEs157fOZDjFqUDpm7eHdq5E8SSR0gUBTEK0cNSHsrSR5a66xs0z3RWuo46QvA3vawp8BxDHvg==} + + '@changesets/get-release-plan@3.0.17': + resolution: {integrity: sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==} + + '@changesets/get-version-range-type@0.3.2': + resolution: {integrity: sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==} + + '@changesets/git@2.0.0': + resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} + + '@changesets/logger@0.0.5': + resolution: {integrity: sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==} + + '@changesets/parse@0.3.16': + resolution: {integrity: sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==} + + '@changesets/pre@1.0.14': + resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} + + '@changesets/read@0.5.9': + resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@5.2.1': + resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} + + '@changesets/write@0.2.3': + resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@types/is-ci@3.0.4': + resolution: {integrity: sha512-AkCYCmwlXeuH89DagDCzvCAyltI2v9lh3U3DqSg/GrBYoReAaWwxfXCqMx9UV5MajLZ4ZFwZzV4cABGIxk2XRw==} + + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + breakword@1.0.6: + resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + + csv-generate@3.4.3: + resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} + + csv-parse@4.16.3: + resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} + + csv-stringify@5.6.5: + resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} + + csv@5.5.3: + resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} + engines: {node: '>= 0.1.90'} + + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + + decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.22.4: + resolution: {integrity: sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + + hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.1: + resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} + engines: {node: '>= 0.4'} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + human-id@1.0.2: + resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + + map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + + map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + + meow@6.1.1: + resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} + engines: {node: '>=8'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + + mixme@0.5.10: + resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} + engines: {node: '>= 8.0.0'} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + preferred-pm@3.1.3: + resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} + engines: {node: '>=10'} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + 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==} + engines: {node: '>= 0.4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.0: + resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} + engines: {node: '>=0.4'} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@7.6.1: + resolution: {integrity: sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==} + engines: {node: '>=10'} + hasBin: true + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.1: + resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + + side-channel@1.0.5: + resolution: {integrity: sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + smartwrap@2.0.2: + resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} + engines: {node: '>=6'} + hasBin: true + + spawndamnit@2.0.0: + resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.17: + resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stream-transform@2.1.3: + resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + + string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + + tty-table@4.2.3: + resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} + engines: {node: '>=8.0.0'} + hasBin: true + + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.5: + resolution: {integrity: sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==} + engines: {node: '>= 0.4'} + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + + which-pm@2.0.0: + resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + engines: {node: '>=8.15'} + + which-typed-array@1.1.14: + resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@babel/code-frame@7.23.5': dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 - dev: true - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-validator-identifier@7.22.20': {} - /@babel/highlight@7.23.4: - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} + '@babel/highlight@7.23.4': dependencies: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true /@babel/runtime@7.24.0: resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 - dev: true - /@changesets/apply-release-plan@6.1.4: - resolution: {integrity: sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==} + '@changesets/apply-release-plan@6.1.4': dependencies: '@babel/runtime': 7.24.0 '@changesets/config': 2.3.1 @@ -65,10 +1065,8 @@ packages: prettier: 2.8.8 resolve-from: 5.0.0 semver: 7.6.1 - dev: true - /@changesets/assemble-release-plan@5.2.4: - resolution: {integrity: sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==} + '@changesets/assemble-release-plan@5.2.4': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.1.4 @@ -76,27 +1074,20 @@ packages: '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 semver: 7.6.1 - dev: true - /@changesets/changelog-git@0.1.14: - resolution: {integrity: sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==} + '@changesets/changelog-git@0.1.14': dependencies: '@changesets/types': 5.2.1 - dev: true - /@changesets/changelog-github@0.4.8: - resolution: {integrity: sha512-jR1DHibkMAb5v/8ym77E4AMNWZKB5NPzw5a5Wtqm1JepAuIF+hrKp2u04NKM14oBZhHglkCfrla9uq8ORnK/dw==} + '@changesets/changelog-github@0.4.8': dependencies: '@changesets/get-github-info': 0.5.2 '@changesets/types': 5.2.1 dotenv: 8.6.0 transitivePeerDependencies: - encoding - dev: true - /@changesets/cli@2.26.2: - resolution: {integrity: sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==} - hasBin: true + '@changesets/cli@2.26.2': dependencies: '@babel/runtime': 7.24.0 '@changesets/apply-release-plan': 6.1.4 @@ -131,10 +1122,8 @@ packages: spawndamnit: 2.0.0 term-size: 2.2.1 tty-table: 4.2.3 - dev: true - /@changesets/config@2.3.1: - resolution: {integrity: sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==} + '@changesets/config@2.3.1': dependencies: '@changesets/errors': 0.1.4 '@changesets/get-dependents-graph': 1.3.6 @@ -143,35 +1132,27 @@ packages: '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 micromatch: 4.0.5 - dev: true - /@changesets/errors@0.1.4: - resolution: {integrity: sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==} + '@changesets/errors@0.1.4': dependencies: extendable-error: 0.1.7 - dev: true - /@changesets/get-dependents-graph@1.3.6: - resolution: {integrity: sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==} + '@changesets/get-dependents-graph@1.3.6': dependencies: '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 semver: 7.6.1 - dev: true - /@changesets/get-github-info@0.5.2: - resolution: {integrity: sha512-JppheLu7S114aEs157fOZDjFqUDpm7eHdq5E8SSR0gUBTEK0cNSHsrSR5a66xs0z3RWuo46QvA3vawp8BxDHvg==} + '@changesets/get-github-info@0.5.2': dependencies: dataloader: 1.4.0 node-fetch: 2.7.0 transitivePeerDependencies: - encoding - dev: true - /@changesets/get-release-plan@3.0.17: - resolution: {integrity: sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==} + '@changesets/get-release-plan@3.0.17': dependencies: '@babel/runtime': 7.24.0 '@changesets/assemble-release-plan': 5.2.4 @@ -180,14 +1161,10 @@ packages: '@changesets/read': 0.5.9 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 - dev: true - /@changesets/get-version-range-type@0.3.2: - resolution: {integrity: sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==} - dev: true + '@changesets/get-version-range-type@0.3.2': {} - /@changesets/git@2.0.0: - resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==} + '@changesets/git@2.0.0': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.1.4 @@ -196,33 +1173,25 @@ packages: is-subdir: 1.2.0 micromatch: 4.0.5 spawndamnit: 2.0.0 - dev: true - /@changesets/logger@0.0.5: - resolution: {integrity: sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==} + '@changesets/logger@0.0.5': dependencies: chalk: 2.4.2 - dev: true - /@changesets/parse@0.3.16: - resolution: {integrity: sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==} + '@changesets/parse@0.3.16': dependencies: '@changesets/types': 5.2.1 js-yaml: 3.14.1 - dev: true - /@changesets/pre@1.0.14: - resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==} + '@changesets/pre@1.0.14': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - dev: true - /@changesets/read@0.5.9: - resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==} + '@changesets/read@0.5.9': dependencies: '@babel/runtime': 7.24.0 '@changesets/git': 2.0.0 @@ -232,37 +1201,27 @@ packages: chalk: 2.4.2 fs-extra: 7.0.1 p-filter: 2.1.0 - dev: true - /@changesets/types@4.1.0: - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} - dev: true + '@changesets/types@4.1.0': {} - /@changesets/types@5.2.1: - resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} - dev: true + '@changesets/types@5.2.1': {} - /@changesets/write@0.2.3: - resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} + '@changesets/write@0.2.3': dependencies: '@babel/runtime': 7.24.0 '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 prettier: 2.8.8 - dev: true - /@manypkg/find-root@1.1.0: - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.24.0 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 - dev: true - /@manypkg/get-packages@1.1.3: - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@manypkg/get-packages@1.1.3': dependencies: '@babel/runtime': 7.24.0 '@changesets/types': 4.1.0 @@ -270,107 +1229,62 @@ packages: fs-extra: 8.1.0 globby: 11.1.0 read-yaml-file: 1.1.0 - dev: true - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - dev: true - /@types/is-ci@3.0.4: - resolution: {integrity: sha512-AkCYCmwlXeuH89DagDCzvCAyltI2v9lh3U3DqSg/GrBYoReAaWwxfXCqMx9UV5MajLZ4ZFwZzV4cABGIxk2XRw==} + '@types/is-ci@3.0.4': dependencies: ci-info: 3.9.0 - dev: true - /@types/minimist@1.2.5: - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - dev: true + '@types/minimist@1.2.5': {} - /@types/node@12.20.55: - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - dev: true + '@types/node@12.20.55': {} - /@types/normalize-package-data@2.4.4: - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - dev: true + '@types/normalize-package-data@2.4.4': {} - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true + '@types/semver@7.5.8': {} - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true + ansi-colors@4.1.3: {} - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true + ansi-regex@5.0.1: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 - dev: true - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: true - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 - dev: true - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} + array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 is-array-buffer: 3.0.4 - dev: true - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true + array-union@2.1.0: {} - /array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} + array.prototype.flat@1.3.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.22.5 es-shim-unscopables: 1.0.2 - dev: true - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} + arraybuffer.prototype.slice@1.0.3: dependencies: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 @@ -380,239 +1294,144 @@ packages: get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 - dev: true - /arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true + arrify@1.0.1: {} - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - dev: true - /better-path-resolve@1.0.0: - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} - engines: {node: '>=4'} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: true - /breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + breakword@1.0.6: dependencies: wcwidth: 1.0.1 - dev: true - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 get-intrinsic: 1.2.4 set-function-length: 1.2.1 - dev: true - /camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} + camelcase-keys@6.2.2: dependencies: camelcase: 5.3.1 map-obj: 4.3.0 quick-lru: 4.0.1 - dev: true - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true + camelcase@5.3.1: {} - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true + chardet@0.7.0: {} - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true + ci-info@3.9.0: {} - /cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + cliui@6.0.0: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - dev: true - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true + clone@1.0.4: {} - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@1.9.3: dependencies: color-name: 1.1.3 - dev: true - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: true - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true + color-name@1.1.3: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + color-name@1.1.4: {} - /cross-spawn@5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + cross-spawn@5.1.0: dependencies: lru-cache: 4.1.5 shebang-command: 1.2.0 which: 1.3.1 - dev: true - /csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - dev: true + csv-generate@3.4.3: {} - /csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - dev: true + csv-parse@4.16.3: {} - /csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - dev: true + csv-stringify@5.6.5: {} - /csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} + csv@5.5.3: dependencies: csv-generate: 3.4.3 csv-parse: 4.16.3 csv-stringify: 5.6.5 stream-transform: 2.1.3 - dev: true - /dataloader@1.4.0: - resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - dev: true + dataloader@1.4.0: {} - /decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 map-obj: 1.0.1 - dev: true - /decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true + decamelize@1.2.0: {} - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + defaults@1.0.4: dependencies: clone: 1.0.4 - dev: true - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 - dev: true - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 has-property-descriptors: 1.0.2 object-keys: 1.1.1 - dev: true - /detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: true + detect-indent@6.1.0: {} - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 - dev: true - /dotenv@8.6.0: - resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} - engines: {node: '>=10'} - dev: true + dotenv@8.6.0: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + emoji-regex@8.0.0: {} - /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} + enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 strip-ansi: 6.0.1 - dev: true - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - dev: true /es-abstract@1.22.5: resolution: {integrity: sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==} @@ -659,204 +1478,126 @@ packages: typed-array-length: 1.0.5 unbox-primitive: 1.0.2 which-typed-array: 1.1.14 - dev: true - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} + es-define-property@1.0.0: dependencies: get-intrinsic: 1.2.4 - dev: true - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true + es-errors@1.3.0: {} - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.3: dependencies: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 hasown: 2.0.1 - dev: true - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + es-shim-unscopables@1.0.2: dependencies: hasown: 2.0.1 - dev: true - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 - dev: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true + escalade@3.1.2: {} - /extendable-error@0.1.7: - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} - dev: true + escape-string-regexp@1.0.5: {} - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} + esprima@4.0.1: {} + + extendable-error@0.1.7: {} + + external-editor@3.1.0: dependencies: chardet: 0.7.0 iconv-lite: 0.4.24 tmp: 0.0.33 - dev: true - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fastq@1.17.1: dependencies: reusify: 1.0.4 - dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: true - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: true - /find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + find-yarn-workspace-root2@1.2.16: dependencies: micromatch: 4.0.5 pkg-dir: 4.2.0 - dev: true - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.3: dependencies: is-callable: 1.2.7 - dev: true - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.11 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true + function-bind@1.1.2: {} - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} + function.prototype.name@1.1.6: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.22.5 functions-have-names: 1.2.3 - dev: true - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true + functions-have-names@1.2.3: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.1 - dev: true - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - dev: true - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} + globalthis@1.0.3: dependencies: define-properties: 1.2.1 - dev: true - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -864,78 +1605,42 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 - dev: true - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 - dev: true - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true + graceful-fs@4.2.11: {} - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true + grapheme-splitter@1.0.4: {} - /hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true + hard-rejection@2.1.0: {} - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true + has-bigints@1.0.2: {} - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true + has-flag@3.0.0: {} - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true + has-flag@4.0.0: {} - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 - dev: true - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true + has-proto@1.0.3: {} - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true + has-symbols@1.0.3: {} - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 - dev: true - /hasown@2.0.1: - resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} - engines: {node: '>= 0.4'} + hasown@2.0.1: dependencies: function-bind: 1.1.2 - dev: true - /hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true + hosted-git-info@2.8.9: {} - /human-id@1.0.2: - resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - dev: true + human-id@1.0.2: {} /husky@9.0.11: resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} @@ -948,263 +1653,147 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true + ignore@5.3.1: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true + indent-string@4.0.0: {} - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} + internal-slot@1.0.7: dependencies: es-errors: 1.3.0 hasown: 2.0.1 side-channel: 1.0.6 dev: true - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} + is-array-buffer@3.0.4: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 - dev: true - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true + is-arrayish@0.2.1: {} - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 - dev: true - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-boolean-object@1.1.2: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: true - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true + is-callable@1.2.7: {} - /is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true + is-ci@3.0.1: dependencies: ci-info: 3.9.0 - dev: true - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.13.1: dependencies: hasown: 2.0.1 - dev: true - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} + is-date-object@1.0.5: dependencies: has-tostringtag: 1.0.2 - dev: true - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true + is-fullwidth-code-point@3.0.0: {} - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - dev: true - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: true + is-negative-zero@2.0.3: {} - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.2 - dev: true - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-number@7.0.0: {} - /is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true + is-plain-obj@1.1.0: {} - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + is-regex@1.1.4: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: true - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} + is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 - dev: true - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 - dev: true - /is-subdir@1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} + is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 - dev: true - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + is-symbol@1.0.4: dependencies: has-symbols: 1.0.3 - dev: true - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} + is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.14 - dev: true - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakref@1.0.2: dependencies: call-bind: 1.0.7 - dev: true - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true + is-windows@1.0.2: {} - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true + isarray@2.0.5: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true + isexe@2.0.0: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true + js-tokens@4.0.0: {} - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true + js-yaml@3.14.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - dev: true - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + json-parse-even-better-errors@2.3.1: {} - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 - dev: true - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true + kind-of@6.0.3: {} - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: true + kleur@4.1.5: {} - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true + lines-and-columns@1.2.4: {} - /load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} + load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.11 js-yaml: 3.14.1 pify: 4.0.1 strip-bom: 3.0.0 - dev: true - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - dev: true - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - dev: true - /lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - dev: true + lodash.startcase@4.4.0: {} - /lru-cache@4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lru-cache@4.1.5: dependencies: pseudomap: 1.0.2 yallist: 2.1.2 - dev: true - /map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true + map-obj@1.0.1: {} - /map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true + map-obj@4.3.0: {} - /meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} + meow@6.1.1: dependencies: '@types/minimist': 1.2.5 camelcase-keys: 6.2.2 @@ -1217,335 +1806,186 @@ packages: trim-newlines: 3.0.1 type-fest: 0.13.1 yargs-parser: 18.1.3 - dev: true - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true + merge2@1.4.1: {} - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromatch@4.0.5: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true - /min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true + min-indent@1.0.1: {} - /minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} + minimist-options@4.1.0: dependencies: arrify: 1.0.1 is-plain-obj: 1.1.0 kind-of: 6.0.3 - dev: true - /mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - dev: true + mixme@0.5.10: {} - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true + node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 - dev: true - /normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 resolve: 1.22.8 semver: 5.7.2 validate-npm-package-license: 3.0.4 - dev: true - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true + object-inspect@1.13.1: {} - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true + object-keys@1.1.1: {} - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} + object.assign@4.1.5: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: true - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true + os-tmpdir@1.0.2: {} - /outdent@0.5.0: - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} - dev: true + outdent@0.5.0: {} - /p-filter@2.1.0: - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} - engines: {node: '>=8'} + p-filter@2.1.0: dependencies: p-map: 2.1.0 - dev: true - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: true - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - dev: true - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: true - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - dev: true - /p-map@2.1.0: - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} - engines: {node: '>=6'} - dev: true + p-map@2.1.0: {} - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true + p-try@2.2.0: {} - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true + path-exists@4.0.0: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true + path-parse@1.0.7: {} - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true + path-type@4.0.0: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picomatch@2.3.1: {} - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true + pify@4.0.1: {} - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 - dev: true - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true + possible-typed-array-names@1.0.0: {} - /preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} - engines: {node: '>=10'} + preferred-pm@3.1.3: dependencies: find-up: 5.0.0 find-yarn-workspace-root2: 1.2.16 path-exists: 4.0.0 which-pm: 2.0.0 - dev: true - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true + prettier@2.8.8: {} - /pseudomap@1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: true + pseudomap@1.0.2: {} - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true + queue-microtask@1.2.3: {} - /quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true + quick-lru@4.0.1: {} - /read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} + read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 read-pkg: 5.2.0 type-fest: 0.8.1 - dev: true - /read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} + read-pkg@5.2.0: dependencies: '@types/normalize-package-data': 2.4.4 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 - dev: true - /read-yaml-file@1.1.0: - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} - engines: {node: '>=6'} + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 js-yaml: 3.14.1 pify: 4.0.1 strip-bom: 3.0.0 - dev: true - /redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} + redent@3.0.0: dependencies: indent-string: 4.0.0 strip-indent: 3.0.0 - dev: true - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - dev: true + regenerator-runtime@0.14.1: {} - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} + regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-errors: 1.3.0 set-function-name: 2.0.2 - dev: true - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true + require-directory@2.1.1: {} - /require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true + require-main-filename@2.0.0: {} - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true + resolve-from@5.0.0: {} - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true + resolve@1.22.8: dependencies: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true + reusify@1.0.4: {} - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - dev: true - /safe-array-concat@1.1.0: - resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} - engines: {node: '>=0.4'} + safe-array-concat@1.1.0: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 has-symbols: 1.0.3 isarray: 2.0.5 - dev: true - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} + safe-regex-test@1.0.3: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-regex: 1.1.4 - dev: true - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true + safer-buffer@2.1.2: {} - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true + semver@5.7.2: {} - /semver@7.6.1: - resolution: {integrity: sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==} - engines: {node: '>=10'} - hasBin: true - dev: true + semver@7.6.1: {} - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true + set-blocking@2.0.0: {} - /set-function-length@1.2.1: - resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==} - engines: {node: '>= 0.4'} + set-function-length@1.2.1: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 @@ -1553,29 +1993,19 @@ packages: get-intrinsic: 1.2.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 - dev: true - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} + set-function-name@2.0.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 - dev: true - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 - dev: true - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true + shebang-regex@1.0.0: {} /side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} @@ -1585,21 +2015,12 @@ packages: es-errors: 1.3.0 get-intrinsic: 1.2.4 object-inspect: 1.13.1 - dev: true - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true + signal-exit@3.0.7: {} - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true + slash@3.0.0: {} - /smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true + smartwrap@2.0.2: dependencies: array.prototype.flat: 1.3.2 breakword: 1.0.6 @@ -1607,151 +2028,94 @@ packages: strip-ansi: 6.0.1 wcwidth: 1.0.1 yargs: 15.4.1 - dev: true - /spawndamnit@2.0.0: - resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + spawndamnit@2.0.0: dependencies: cross-spawn: 5.1.0 signal-exit: 3.0.7 - dev: true - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.17 - dev: true - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true + spdx-exceptions@2.5.0: {} - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 spdx-license-ids: 3.0.17 - dev: true - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true + spdx-license-ids@3.0.17: {} - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true + sprintf-js@1.0.3: {} - /stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + stream-transform@2.1.3: dependencies: mixme: 0.5.10 - dev: true - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true - /string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} - engines: {node: '>= 0.4'} + string.prototype.trim@1.2.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.22.5 dev: true - /string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + string.prototype.trimend@1.0.7: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.22.5 dev: true - /string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string.prototype.trimstart@1.0.7: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.22.5 dev: true - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: true - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true + strip-bom@3.0.0: {} - /strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 - dev: true - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - dev: true - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - dev: true - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true + supports-preserve-symlinks-flag@1.0.0: {} - /term-size@2.2.1: - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} - engines: {node: '>=8'} - dev: true + term-size@2.2.1: {} - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 - dev: true - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true + tr46@0.0.3: {} - /trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true + trim-newlines@3.0.1: {} - /tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true + tty-table@4.2.3: dependencies: chalk: 4.1.2 csv: 5.5.3 @@ -1760,46 +2124,28 @@ packages: strip-ansi: 6.0.1 wcwidth: 1.0.1 yargs: 17.7.2 - dev: true - /type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} - dev: true + type-fest@0.13.1: {} - /type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true + type-fest@0.6.0: {} - /type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true + type-fest@0.8.1: {} - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} + typed-array-buffer@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-typed-array: 1.1.13 - dev: true - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} + typed-array-byte-length@1.0.1: 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 - dev: true - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} + typed-array-byte-offset@1.0.2: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -1807,11 +2153,8 @@ packages: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - dev: true - /typed-array-length@1.0.5: - resolution: {integrity: sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==} - engines: {node: '>= 0.4'} + typed-array-length@1.0.5: dependencies: call-bind: 1.0.7 for-each: 0.3.3 @@ -1819,133 +2162,85 @@ packages: has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - dev: true - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.7 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: true - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true + universalify@0.1.2: {} - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - dev: true - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + wcwidth@1.0.1: dependencies: defaults: 1.0.4 - dev: true - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true + webidl-conversions@3.0.1: {} - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 is-boolean-object: 1.1.2 is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 - dev: true - /which-module@2.0.1: - resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - dev: true + which-module@2.0.1: {} - /which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} + which-pm@2.0.0: dependencies: load-yaml-file: 0.2.0 path-exists: 4.0.0 - dev: true - /which-typed-array@1.1.14: - resolution: {integrity: sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==} - engines: {node: '>= 0.4'} + which-typed-array@1.1.14: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.2 - dev: true - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true + which@1.3.1: dependencies: isexe: 2.0.0 - dev: true - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true + y18n@4.0.3: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + y18n@5.0.8: {} - /yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: true + yallist@2.1.2: {} - /yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 decamelize: 1.2.0 - dev: true - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true + yargs-parser@21.1.1: {} - /yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} + yargs@15.4.1: dependencies: cliui: 6.0.0 decamelize: 1.2.0 @@ -1958,11 +2253,8 @@ packages: which-module: 2.0.1 y18n: 4.0.3 yargs-parser: 18.1.3 - dev: true - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@17.7.2: dependencies: cliui: 8.0.1 escalade: 3.1.2 @@ -1971,9 +2263,5 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true + yocto-queue@0.1.0: {} diff --git a/testdata/scripts/health/default.txtar b/testdata/scripts/health/default.txtar index 4ca7fba925..1dbf6b8eb9 100644 --- a/testdata/scripts/health/default.txtar +++ b/testdata/scripts/health/default.txtar @@ -37,6 +37,7 @@ ok Mercury.WSRPCPool ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner +ok PipelineRunner.BridgeCache ok PromReporter ok TelemetryManager @@ -97,6 +98,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "PipelineRunner.BridgeCache", + "attributes": { + "name": "PipelineRunner.BridgeCache", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "PromReporter", diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar index fd48c0ad1c..8178f8e821 100644 --- a/testdata/scripts/health/multi-chain.txtar +++ b/testdata/scripts/health/multi-chain.txtar @@ -81,6 +81,7 @@ ok Mercury.WSRPCPool ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner +ok PipelineRunner.BridgeCache ok PromReporter ok Solana.Bar ok StarkNet.Baz @@ -269,6 +270,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "PipelineRunner.BridgeCache", + "attributes": { + "name": "PipelineRunner.BridgeCache", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "PromReporter", diff --git a/testdata/scripts/keys/eth/list/help.txtar b/testdata/scripts/keys/eth/list/help.txtar index d7156fd3e6..2fa0f957ce 100644 --- a/testdata/scripts/keys/eth/list/help.txtar +++ b/testdata/scripts/keys/eth/list/help.txtar @@ -6,4 +6,4 @@ NAME: chainlink keys eth list - List available Ethereum accounts with their ETH & LINK balances and other metadata USAGE: - chainlink keys eth list [arguments...] \ No newline at end of file + chainlink keys eth list [arguments...] diff --git a/testdata/scripts/node/db/preparetest/help.txtar b/testdata/scripts/node/db/preparetest/help.txtar index 0173cd5b6c..7ba7450a79 100644 --- a/testdata/scripts/node/db/preparetest/help.txtar +++ b/testdata/scripts/node/db/preparetest/help.txtar @@ -11,4 +11,5 @@ USAGE: OPTIONS: --user-only only include test user fixture + --force set to true to force the reset by dropping any existing connections to the database diff --git a/testdata/scripts/node/db/reset/help.txtar b/testdata/scripts/node/db/reset/help.txtar index 2f03884be9..d69a062452 100644 --- a/testdata/scripts/node/db/reset/help.txtar +++ b/testdata/scripts/node/db/reset/help.txtar @@ -11,4 +11,5 @@ USAGE: OPTIONS: --dangerWillRobinson set to true to enable dropping non-test databases + --force set to true to force the reset by dropping any existing connections to the database diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index 1997f60c03..928c7d2adc 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -262,6 +262,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + Invalid configuration: invalid secrets: 2 errors: - Database.URL: empty: must be provided and non-empty - Password.Keystore: empty: must be provided and non-empty diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index e6cdf74359..571eb3a5ba 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -306,6 +306,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 756653edad..2dc24dd4eb 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -306,6 +306,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index e2c60c7742..6769552771 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -306,6 +306,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 00bda8d730..e38b150841 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -291,6 +291,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + Invalid configuration: invalid configuration: P2P.V2.Enabled: invalid value (false): P2P required for OCR or OCR2. Please enable P2P or disable OCR/OCR2. -- err.txt -- diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index bb7bc2a630..3f2dc1d7d2 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -296,6 +296,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index d7136ae78c..6afc5cd82a 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -303,6 +303,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + [[EVM]] ChainID = '1' AutoCreateKey = true diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 8635f1cf2a..a5915cbe58 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -285,6 +285,11 @@ DeltaDial = '15s' DeltaReconcile = '1m0s' ListenAddresses = [] +[Capabilities.ExternalRegistry] +Address = '' +NetworkID = 'evm' +ChainID = '1' + # Configuration warning: Tracing.TLSCertPath: invalid value (something): must be empty when Tracing.Mode is 'unencrypted' -Valid configuration. \ No newline at end of file +Valid configuration. diff --git a/tools/bin/modgraph b/tools/bin/modgraph index b61264cb02..4d8ad108c6 100755 --- a/tools/bin/modgraph +++ b/tools/bin/modgraph @@ -9,9 +9,13 @@ echo "# smartcontractkit Go modules flowchart LR subgraph chains chainlink-cosmos - chainlink-evm chainlink-solana chainlink-starknet/relayer + subgraph chainlink-integrations + direction LR + chainlink-integrations/evm/relayer + chainlink-integrations/common + end end subgraph products