From 30d0f0a517337144e432fd9bb2f3f1579dbcde5a Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Sun, 30 Jul 2023 14:35:00 +0100 Subject: [PATCH] Contracts V3 (#882) Co-authored-by: David Dunn <26876072+doubledup@users.noreply.github.com> Co-authored-by: Clara van Staden Co-authored-by: Alistair Singh Co-authored-by: Ron Co-authored-by: claravanstaden --- .github/workflows/contracts.yml | 36 + .github/workflows/ethereum.yml | 51 - .gitignore | 3 + .gitmodules | 22 +- README.md | 22 +- _typos.toml | 2 +- codecov.yml | 12 +- .../contracts => contracts}/.editorconfig | 0 .../contracts => contracts}/.envrc-example | 2 + contracts/.gas-snapshot | 70 + .../contracts => contracts}/.gitignore | 1 + .../packages/contracts => contracts}/LICENSE | 0 contracts/README.md | 71 + .../contracts => contracts}/foundry.toml | 4 +- .../lib/canonical-weth | 0 .../contracts => contracts}/lib/ds-test | 0 contracts/lib/forge-std | 1 + contracts/lib/openzeppelin-contracts | 1 + .../contracts => contracts}/remappings.txt | 0 .../scripts/minsigs.py | 0 contracts/src/Agent.sol | 35 + contracts/src/AgentExecutor.sol | 41 + contracts/src/Assets.sol | 113 + .../src/BeefyClient.sol | 64 +- contracts/src/DeployScript.sol | 84 + contracts/src/Gateway.sol | 562 ++++ contracts/src/GatewayProxy.sol | 45 + contracts/src/SubstrateTypes.sol | 131 + contracts/src/Types.sol | 74 + contracts/src/Verification.sol | 264 ++ contracts/src/interfaces/IERC20.sol | 80 + contracts/src/interfaces/IGateway.sol | 80 + contracts/src/interfaces/IInitializable.sol | 12 + contracts/src/storage/AssetsStorage.sol | 22 + contracts/src/storage/CoreStorage.sol | 31 + contracts/src/utils/Address.sol | 15 + .../src/utils/Bitfield.sol | 2 +- .../src/utils/Bits.sol | 0 contracts/src/utils/Call.sol | 25 + contracts/src/utils/ERC1967.sol | 21 + .../src/utils/MMRProof.sol | 9 + contracts/src/utils/SafeTransfer.sol | 44 + .../src/utils}/ScaleCodec.sol | 34 +- .../src/utils/SubstrateMerkleProof.sol | 7 +- contracts/test/Agent.t.sol | 51 + .../test/BeefyClient.t.sol | 251 +- contracts/test/Gateway.t.sol | 653 ++++ contracts/test/MMRProof.t.sol | 56 + contracts/test/ScaleCodec.t.sol | 50 + .../test/Verification.t.sol | 64 +- .../test/data/beefy-commitment.json | 0 contracts/test/data/beefy-final-bitfield.json | 9 + contracts/test/data/beefy-final-proof.json | 840 +++++ contracts/test/data/beefy-validator-set.json | 308 ++ .../data/mmr-fixture-data-15-leaves.json | 0 .../test/mocks/BeefyClientMock.sol | 20 +- contracts/test/mocks/GatewayMock.sol | 93 + .../test/mocks/MMRProofWrapper.sol | 4 +- contracts/test/mocks/VerificationWrapper.sol | 22 + core/package.json | 24 - core/packages/contracts/.gas-snapshot | 44 - core/packages/contracts/.mocharc.json | 6 - core/packages/contracts/.solcover.js | 3 - core/packages/contracts/.solhint.json | 10 - core/packages/contracts/.solhintignore | 6 - core/packages/contracts/README.md | 56 - core/packages/contracts/lib/forge-std | 1 - .../contracts/lib/openzeppelin-contracts | 1 - core/packages/contracts/package.json | 77 - core/packages/contracts/scripts/ffiWrapper.ts | 63 - .../contracts/scripts/generateContractInfo.js | 42 - core/packages/contracts/src/Auth.sol | 14 - core/packages/contracts/src/DeployScript.sol | 137 - core/packages/contracts/src/Gateway.sol | 36 - .../packages/contracts/src/IOutboundQueue.sol | 11 - .../contracts/src/IParachainClient.sol | 7 - core/packages/contracts/src/IRecipient.sol | 9 - core/packages/contracts/src/InboundQueue.sol | 117 - core/packages/contracts/src/NativeTokens.sol | 148 - .../contracts/src/NativeTokensTypes.sol | 61 - core/packages/contracts/src/OutboundQueue.sol | 44 - .../contracts/src/ParachainClient.sol | 240 -- core/packages/contracts/src/Registry.sol | 26 - .../packages/contracts/src/RegistryLookup.sol | 23 - .../contracts/src/SovereignTreasury.sol | 46 - .../packages/contracts/src/SubstrateTypes.sol | 51 - core/packages/contracts/src/TokenVault.sol | 52 - core/packages/contracts/src/Types.sol | 19 - core/packages/contracts/src/UpgradeProxy.sol | 49 - core/packages/contracts/src/UpgradeTask.sol | 11 - core/packages/contracts/src/Vault.sol | 52 - core/packages/contracts/src/utils/Bytes.sol | 148 - core/packages/contracts/src/utils/Memory.sol | 91 - .../contracts/src/utils/OpaqueProof.sol | 12 - .../contracts/test/InboundQueue.t.sol | 120 - .../contracts/test/NativeTokens.t.sol | 140 - .../contracts/test/OutboundQueue.t.sol | 38 - core/packages/contracts/test/ScaleCodec.t.sol | 32 - core/packages/contracts/test/TokenVault.t.sol | 81 - .../contracts/test/UpgradeProxy.t.sol | 71 - .../test/archive/libs/bitfield.test.ts | 29 - .../libs/data/mmr-fixture-data-7-leaves.json | 69 - .../test/archive/libs/mmr_proof.test.ts | 131 - .../test/mocks/OutboundQueueMock.sol | 13 - .../test/mocks/ParachainClientMock.sol | 30 - .../contracts/test/mocks/RecipientMock.sol | 46 - .../contracts/test/mocks/UpgradeTaskMock.sol | 28 - core/packages/test/scripts/configure-beefy.sh | 42 - core/pnpm-workspace.yaml | 4 - cumulus | 2 +- docs/architecture/apps/dot.md | 2 +- docs/architecture/apps/erc20.md | 2 +- docs/architecture/apps/ether.md | 2 +- .../verification/polkadot/README.md | 12 +- docs/other/quick-start-guide.md | 16 +- flake.lock | 6 +- flake.nix | 19 +- go.work | 3 + go.work.sum | 42 + parachain/Cargo.lock | 74 +- parachain/Cargo.toml | 1 - parachain/README.md | 8 +- parachain/pallets/control/Cargo.toml | 13 +- parachain/pallets/control/src/benchmarking.rs | 19 +- parachain/pallets/control/src/lib.rs | 136 +- parachain/pallets/control/src/mock.rs | 146 +- parachain/pallets/control/src/tests.rs | 171 ++ parachain/pallets/control/src/weights.rs | 15 +- .../pallets/ethereum-beacon-client/Cargo.toml | 1 - .../pallets/ethereum-beacon-client/src/lib.rs | 38 +- .../ethereum-beacon-client/src/mock.rs | 22 +- .../ethereum-beacon-client/src/tests.rs | 2 +- parachain/pallets/inbound-queue/Cargo.toml | 4 +- .../src/benchmarking/fixtures.rs | 26 +- .../inbound-queue/src/benchmarking/mod.rs | 35 +- .../pallets/inbound-queue/src/envelope.rs | 12 +- parachain/pallets/inbound-queue/src/lib.rs | 139 +- parachain/pallets/inbound-queue/src/test.rs | 154 +- .../outbound-queue/src/benchmarking.rs | 10 +- parachain/pallets/outbound-queue/src/lib.rs | 92 +- parachain/pallets/outbound-queue/src/test.rs | 24 +- parachain/primitives/core/Cargo.toml | 6 +- .../core/src/{types.rs => inbound.rs} | 38 +- parachain/primitives/core/src/lib.rs | 95 +- parachain/primitives/core/src/outbound.rs | 231 ++ parachain/primitives/ethereum/Cargo.toml | 1 - parachain/primitives/router/Cargo.toml | 2 + .../primitives/router/src/inbound/mod.rs | 170 +- .../primitives/router/src/outbound/mod.rs | 459 ++- .../primitives/router/src/outbound/payload.rs | 79 - parachain/primitives/testutils/Cargo.toml | 11 - parachain/primitives/testutils/src/lib.rs | 127 - relayer/README.md | 6 +- relayer/chain/ethereum/connection.go | 127 +- relayer/chain/ethereum/connection_test.go | 21 - relayer/chain/ethereum/message.go | 1 + relayer/chain/parachain/writer.go | 3 + relayer/cmd/generate_beacon_data.go | 4 +- relayer/cmd/import_execution_header.go | 2 +- relayer/contracts/beefy_client.go | 328 +- relayer/contracts/gateway.go | 1921 ++++++++++++ relayer/contracts/generate.go | 6 +- relayer/contracts/inbound_queue.go | 2113 ------------- relayer/contracts/opaque_proof.go | 251 -- relayer/contracts/outbound_queue.go | 1369 --------- .../header/syncer/sync_protocol_test.go | 2 +- .../beacon/header/syncer/syncer_test.go | 4 +- relayer/relays/beefy/ethereum-writer.go | 114 +- relayer/relays/beefy/main.go | 2 +- relayer/relays/beefy/task_test.go | 19 - relayer/relays/execution/config.go | 6 +- relayer/relays/execution/main.go | 91 +- relayer/relays/parachain/config.go | 9 +- relayer/relays/parachain/ethereum-writer.go | 189 +- relayer/relays/parachain/logger.go | 68 +- relayer/relays/parachain/main.go | 2 +- relayer/relays/parachain/scanner.go | 65 +- relayer/relays/parachain/types.go | 22 +- relayer/revive.toml | 1 - scripts/init.sh | 8 + .husky/pre-commit => scripts/pre-commit.sh | 29 +- smoketest/.gitignore | 2 - smoketest/README.md | 27 +- smoketest/make-bindings.sh | 10 +- smoketest/src/parachains/mod.rs | 4 +- .../{create_token.rs => register_token.rs} | 36 +- .../tests/{lock_tokens.rs => send_token.rs} | 38 +- {core => web}/.editorconfig | 0 {core => web}/.gitignore | 0 {core => web}/.nvmrc | 0 {core => web}/README.md | 0 {core => web}/init.sh | 5 +- web/package.json | 22 + {core => web}/packages/api/.editorconfig | 0 {core => web}/packages/api/.eslintrc.json | 0 {core => web}/packages/api/.gitignore | 0 {core => web}/packages/api/.prettierrc | 0 {core => web}/packages/api/README.md | 0 {core => web}/packages/api/package.json | 21 +- {core => web}/packages/api/src/index.ts | 29 +- {core => web}/packages/api/tsconfig.json | 12 +- web/packages/contract-types/.editorconfig | 4 + web/packages/contract-types/.gitignore | 4 + web/packages/contract-types/README.md | 1 + web/packages/contract-types/package.json | 31 + web/packages/contract-types/tsconfig.json | 26 + web/packages/test-helpers/.editorconfig | 4 + .../packages/test-helpers}/.eslintrc.json | 13 +- web/packages/test-helpers/.gitignore | 2 + .../packages/test-helpers}/.prettierrc | 0 web/packages/test-helpers/README.md | 1 + web/packages/test-helpers/package.json | 53 + .../src/generateBeefyCheckpoint.ts | 40 +- .../src/generateBeefyTestFixture.ts | 85 + .../test-helpers/src/generateContractInfo.ts | 49 + .../packages/test-helpers/src}/helpers.ts | 10 +- .../packages/test-helpers/src}/wallets.ts | 0 .../packages/test-helpers}/tsconfig.json | 8 +- {core => web}/packages/test/.envrc-example | 2 +- {core => web}/packages/test/.gitignore | 0 {core => web}/packages/test/README.md | 0 .../packages/test/config/beacon-relay.json | 0 .../packages/test/config/beefy-relay.json | 0 .../test/config/dev-example-ethereum-keys | 0 .../packages/test/config/dev-example-key0.prv | 0 .../packages/test/config/dev-example-key1.prv | 0 .../packages/test/config/execution-relay.json | 4 +- .../packages/test/config/genesis.json | 2 +- {core => web}/packages/test/config/jwtsecret | 0 .../packages/test/config/launch-config.toml | 0 .../packages/test/config/parachain-relay.json | 6 +- .../packages/test/docs/burn-polkaeth.jpeg | Bin .../packages/test/docs/query-balance.jpeg | Bin {core => web}/packages/test/package.json | 6 +- .../packages/test/scripts/build-binary.sh | 0 .../test/scripts/configure-bridgehub.sh | 5 +- .../packages/test/scripts/deploy-contracts.sh | 6 +- .../packages/test/scripts/deploy-ethereum.sh | 16 - .../packages/test/scripts/deploy-polkadot.sh | 0 .../test/scripts/fetch-beacon-data.sh | 0 .../test/scripts/generate-beefy-checkpoint.sh | 17 + .../test/scripts/helpers/make-xcm-transfer.ts | 0 .../scripts/helpers/overrideParachainSpec.js | 0 .../scripts/helpers/poll-ethereum-events.ts | 0 .../helpers/subscribeBeefyJustifications.js | 0 .../scripts/helpers/transformEthHeader.js | 0 .../packages/test/scripts/set-env.sh | 32 +- .../packages/test/scripts/start-goerli.sh | 0 .../packages/test/scripts/start-relayer.sh | 28 +- .../packages/test/scripts/start-services.sh | 22 +- .../packages/test/scripts/wait-for-it.sh | 0 .../packages/test/scripts/xcm-helper.sh | 10 +- {core => web}/packages/test/src/.gitkeep | 0 {core => web}/packages/test/tsconfig.json | 0 {core => web}/pnpm-lock.yaml | 2698 ++++------------- web/pnpm-workspace.yaml | 5 + {core => web}/tsconfig.json | 0 {core => web}/turbo.json | 0 258 files changed, 8975 insertions(+), 10796 deletions(-) create mode 100644 .github/workflows/contracts.yml delete mode 100644 .github/workflows/ethereum.yml rename {core/packages/contracts => contracts}/.editorconfig (100%) rename {core/packages/contracts => contracts}/.envrc-example (88%) create mode 100644 contracts/.gas-snapshot rename {core/packages/contracts => contracts}/.gitignore (96%) rename {core/packages/contracts => contracts}/LICENSE (100%) create mode 100644 contracts/README.md rename {core/packages/contracts => contracts}/foundry.toml (57%) rename {core/packages/contracts => contracts}/lib/canonical-weth (100%) rename {core/packages/contracts => contracts}/lib/ds-test (100%) create mode 160000 contracts/lib/forge-std create mode 160000 contracts/lib/openzeppelin-contracts rename {core/packages/contracts => contracts}/remappings.txt (100%) rename {core/packages/contracts => contracts}/scripts/minsigs.py (100%) create mode 100644 contracts/src/Agent.sol create mode 100644 contracts/src/AgentExecutor.sol create mode 100644 contracts/src/Assets.sol rename {core/packages/contracts => contracts}/src/BeefyClient.sol (95%) create mode 100644 contracts/src/DeployScript.sol create mode 100644 contracts/src/Gateway.sol create mode 100644 contracts/src/GatewayProxy.sol create mode 100644 contracts/src/SubstrateTypes.sol create mode 100644 contracts/src/Types.sol create mode 100644 contracts/src/Verification.sol create mode 100644 contracts/src/interfaces/IERC20.sol create mode 100644 contracts/src/interfaces/IGateway.sol create mode 100644 contracts/src/interfaces/IInitializable.sol create mode 100644 contracts/src/storage/AssetsStorage.sol create mode 100644 contracts/src/storage/CoreStorage.sol create mode 100644 contracts/src/utils/Address.sol rename {core/packages/contracts => contracts}/src/utils/Bitfield.sol (99%) rename {core/packages/contracts => contracts}/src/utils/Bits.sol (100%) create mode 100644 contracts/src/utils/Call.sol create mode 100644 contracts/src/utils/ERC1967.sol rename {core/packages/contracts => contracts}/src/utils/MMRProof.sol (80%) create mode 100644 contracts/src/utils/SafeTransfer.sol rename {core/packages/contracts/src => contracts/src/utils}/ScaleCodec.sol (78%) rename core/packages/contracts/src/utils/MerkleProof.sol => contracts/src/utils/SubstrateMerkleProof.sol (90%) create mode 100644 contracts/test/Agent.t.sol rename {core/packages/contracts => contracts}/test/BeefyClient.t.sol (65%) create mode 100644 contracts/test/Gateway.t.sol create mode 100644 contracts/test/MMRProof.t.sol create mode 100644 contracts/test/ScaleCodec.t.sol rename core/packages/contracts/test/ParachainClient.t.sol => contracts/test/Verification.t.sol (61%) rename {core/packages/contracts => contracts}/test/data/beefy-commitment.json (100%) create mode 100644 contracts/test/data/beefy-final-bitfield.json create mode 100644 contracts/test/data/beefy-final-proof.json create mode 100644 contracts/test/data/beefy-validator-set.json rename {core/packages/contracts/test/archive/libs => contracts/test}/data/mmr-fixture-data-15-leaves.json (100%) rename {core/packages/contracts => contracts}/test/mocks/BeefyClientMock.sol (57%) create mode 100644 contracts/test/mocks/GatewayMock.sol rename {core/packages/contracts => contracts}/test/mocks/MMRProofWrapper.sol (79%) create mode 100644 contracts/test/mocks/VerificationWrapper.sol delete mode 100644 core/package.json delete mode 100644 core/packages/contracts/.gas-snapshot delete mode 100644 core/packages/contracts/.mocharc.json delete mode 100644 core/packages/contracts/.solcover.js delete mode 100644 core/packages/contracts/.solhint.json delete mode 100644 core/packages/contracts/.solhintignore delete mode 100644 core/packages/contracts/README.md delete mode 160000 core/packages/contracts/lib/forge-std delete mode 160000 core/packages/contracts/lib/openzeppelin-contracts delete mode 100644 core/packages/contracts/package.json delete mode 100755 core/packages/contracts/scripts/ffiWrapper.ts delete mode 100644 core/packages/contracts/scripts/generateContractInfo.js delete mode 100644 core/packages/contracts/src/Auth.sol delete mode 100644 core/packages/contracts/src/DeployScript.sol delete mode 100644 core/packages/contracts/src/Gateway.sol delete mode 100644 core/packages/contracts/src/IOutboundQueue.sol delete mode 100644 core/packages/contracts/src/IParachainClient.sol delete mode 100644 core/packages/contracts/src/IRecipient.sol delete mode 100644 core/packages/contracts/src/InboundQueue.sol delete mode 100644 core/packages/contracts/src/NativeTokens.sol delete mode 100644 core/packages/contracts/src/NativeTokensTypes.sol delete mode 100644 core/packages/contracts/src/OutboundQueue.sol delete mode 100644 core/packages/contracts/src/ParachainClient.sol delete mode 100644 core/packages/contracts/src/Registry.sol delete mode 100644 core/packages/contracts/src/RegistryLookup.sol delete mode 100644 core/packages/contracts/src/SovereignTreasury.sol delete mode 100644 core/packages/contracts/src/SubstrateTypes.sol delete mode 100644 core/packages/contracts/src/TokenVault.sol delete mode 100644 core/packages/contracts/src/Types.sol delete mode 100644 core/packages/contracts/src/UpgradeProxy.sol delete mode 100644 core/packages/contracts/src/UpgradeTask.sol delete mode 100644 core/packages/contracts/src/Vault.sol delete mode 100644 core/packages/contracts/src/utils/Bytes.sol delete mode 100644 core/packages/contracts/src/utils/Memory.sol delete mode 100644 core/packages/contracts/src/utils/OpaqueProof.sol delete mode 100644 core/packages/contracts/test/InboundQueue.t.sol delete mode 100644 core/packages/contracts/test/NativeTokens.t.sol delete mode 100644 core/packages/contracts/test/OutboundQueue.t.sol delete mode 100644 core/packages/contracts/test/ScaleCodec.t.sol delete mode 100644 core/packages/contracts/test/TokenVault.t.sol delete mode 100644 core/packages/contracts/test/UpgradeProxy.t.sol delete mode 100644 core/packages/contracts/test/archive/libs/bitfield.test.ts delete mode 100644 core/packages/contracts/test/archive/libs/data/mmr-fixture-data-7-leaves.json delete mode 100644 core/packages/contracts/test/archive/libs/mmr_proof.test.ts delete mode 100644 core/packages/contracts/test/mocks/OutboundQueueMock.sol delete mode 100644 core/packages/contracts/test/mocks/ParachainClientMock.sol delete mode 100644 core/packages/contracts/test/mocks/RecipientMock.sol delete mode 100644 core/packages/contracts/test/mocks/UpgradeTaskMock.sol delete mode 100755 core/packages/test/scripts/configure-beefy.sh delete mode 100644 core/pnpm-workspace.yaml create mode 100644 go.work create mode 100644 go.work.sum rename parachain/primitives/core/src/{types.rs => inbound.rs} (58%) create mode 100644 parachain/primitives/core/src/outbound.rs delete mode 100644 parachain/primitives/router/src/outbound/payload.rs delete mode 100644 parachain/primitives/testutils/Cargo.toml delete mode 100644 parachain/primitives/testutils/src/lib.rs delete mode 100644 relayer/chain/ethereum/connection_test.go create mode 100644 relayer/contracts/gateway.go delete mode 100644 relayer/contracts/inbound_queue.go delete mode 100644 relayer/contracts/opaque_proof.go delete mode 100644 relayer/contracts/outbound_queue.go create mode 100755 scripts/init.sh rename .husky/pre-commit => scripts/pre-commit.sh (65%) rename smoketest/tests/{create_token.rs => register_token.rs} (53%) rename smoketest/tests/{lock_tokens.rs => send_token.rs} (64%) rename {core => web}/.editorconfig (100%) rename {core => web}/.gitignore (100%) rename {core => web}/.nvmrc (100%) rename {core => web}/README.md (100%) rename {core => web}/init.sh (72%) create mode 100644 web/package.json rename {core => web}/packages/api/.editorconfig (100%) rename {core => web}/packages/api/.eslintrc.json (100%) rename {core => web}/packages/api/.gitignore (100%) rename {core => web}/packages/api/.prettierrc (100%) rename {core => web}/packages/api/README.md (100%) rename {core => web}/packages/api/package.json (58%) rename {core => web}/packages/api/src/index.ts (62%) rename {core => web}/packages/api/tsconfig.json (83%) create mode 100644 web/packages/contract-types/.editorconfig create mode 100644 web/packages/contract-types/.gitignore create mode 100644 web/packages/contract-types/README.md create mode 100644 web/packages/contract-types/package.json create mode 100644 web/packages/contract-types/tsconfig.json create mode 100644 web/packages/test-helpers/.editorconfig rename {core/packages/contracts => web/packages/test-helpers}/.eslintrc.json (64%) create mode 100644 web/packages/test-helpers/.gitignore rename {core/packages/contracts => web/packages/test-helpers}/.prettierrc (100%) create mode 100644 web/packages/test-helpers/README.md create mode 100644 web/packages/test-helpers/package.json rename core/packages/contracts/scripts/configure-beefy.ts => web/packages/test-helpers/src/generateBeefyCheckpoint.ts (67%) mode change 100644 => 100755 create mode 100755 web/packages/test-helpers/src/generateBeefyTestFixture.ts create mode 100644 web/packages/test-helpers/src/generateContractInfo.ts rename {core/packages/contracts/scripts => web/packages/test-helpers/src}/helpers.ts (91%) rename {core/packages/contracts/scripts => web/packages/test-helpers/src}/wallets.ts (100%) rename {core/packages/contracts => web/packages/test-helpers}/tsconfig.json (81%) rename {core => web}/packages/test/.envrc-example (90%) rename {core => web}/packages/test/.gitignore (100%) rename {core => web}/packages/test/README.md (100%) rename {core => web}/packages/test/config/beacon-relay.json (100%) rename {core => web}/packages/test/config/beefy-relay.json (100%) rename {core => web}/packages/test/config/dev-example-ethereum-keys (100%) rename {core => web}/packages/test/config/dev-example-key0.prv (100%) rename {core => web}/packages/test/config/dev-example-key1.prv (100%) rename {core => web}/packages/test/config/execution-relay.json (84%) rename {core => web}/packages/test/config/genesis.json (97%) rename {core => web}/packages/test/config/jwtsecret (100%) rename {core => web}/packages/test/config/launch-config.toml (100%) rename {core => web}/packages/test/config/parachain-relay.json (86%) rename {core => web}/packages/test/docs/burn-polkaeth.jpeg (100%) rename {core => web}/packages/test/docs/query-balance.jpeg (100%) rename {core => web}/packages/test/package.json (83%) rename {core => web}/packages/test/scripts/build-binary.sh (100%) rename {core => web}/packages/test/scripts/configure-bridgehub.sh (94%) rename {core => web}/packages/test/scripts/deploy-contracts.sh (88%) rename {core => web}/packages/test/scripts/deploy-ethereum.sh (85%) rename {core => web}/packages/test/scripts/deploy-polkadot.sh (100%) rename {core => web}/packages/test/scripts/fetch-beacon-data.sh (100%) create mode 100755 web/packages/test/scripts/generate-beefy-checkpoint.sh rename {core => web}/packages/test/scripts/helpers/make-xcm-transfer.ts (100%) rename {core => web}/packages/test/scripts/helpers/overrideParachainSpec.js (100%) rename {core => web}/packages/test/scripts/helpers/poll-ethereum-events.ts (100%) rename {core => web}/packages/test/scripts/helpers/subscribeBeefyJustifications.js (100%) rename {core => web}/packages/test/scripts/helpers/transformEthHeader.js (100%) rename {core => web}/packages/test/scripts/set-env.sh (88%) rename {core => web}/packages/test/scripts/start-goerli.sh (100%) rename {core => web}/packages/test/scripts/start-relayer.sh (88%) rename {core => web}/packages/test/scripts/start-services.sh (83%) rename {core => web}/packages/test/scripts/wait-for-it.sh (100%) rename {core => web}/packages/test/scripts/xcm-helper.sh (92%) rename {core => web}/packages/test/src/.gitkeep (100%) rename {core => web}/packages/test/tsconfig.json (100%) rename {core => web}/pnpm-lock.yaml (82%) create mode 100644 web/pnpm-workspace.yaml rename {core => web}/tsconfig.json (100%) rename {core => web}/turbo.json (100%) diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml new file mode 100644 index 0000000000000..a243cd87392f0 --- /dev/null +++ b/.github/workflows/contracts.yml @@ -0,0 +1,36 @@ +name: contracts + +on: + push: + paths: + - "contracts/**" + - "!contracts/**/README.md" + branches: + - main + pull_request: + paths: + - "contracts/**" + - "!contracts/**/README.md" + +jobs: + build: + runs-on: snowbridge-runner + timeout-minutes: 15 + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 2 + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + - name: Test + working-directory: contracts + run: forge test + - name: Coverage + working-directory: contracts + run: forge coverage --report=lcov --via-ir + - name: Upload coverage reports to Codecov with GitHub Action + uses: codecov/codecov-action@v3 + with: + working-directory: contracts + files: lcov.info + flags: solidity diff --git a/.github/workflows/ethereum.yml b/.github/workflows/ethereum.yml deleted file mode 100644 index 3c0ccc8b1862b..0000000000000 --- a/.github/workflows/ethereum.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: ethereum - -on: - push: - paths: - - "core/**" - - "!core/**/README.md" - branches: - - main - pull_request: - paths: - - "core/**" - - "!core/**/README.md" - -jobs: - build: - runs-on: snowbridge-runner - timeout-minutes: 15 - steps: - - uses: actions/checkout@v1 - with: - fetch-depth: 2 - - uses: pnpm/action-setup@v2.0.1 - with: - version: 8.6.6 - - name: Setup Node.js environment - uses: actions/setup-node@v3 - with: - node-version: v18.16.1 - cache: "pnpm" - cache-dependency-path: core/pnpm-lock.yaml - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Install dependencies and Build all - working-directory: core - run: pnpm install --frozen-lockfile && pnpm build - - name: Test - working-directory: core/packages/contracts - run: forge test - - name: Coverage - working-directory: core/packages/contracts - run: forge coverage --report=lcov --via-ir - - name: Lint - working-directory: core/packages/contracts - run: pnpm lint - - name: Upload coverage reports to Codecov with GitHub Action - uses: codecov/codecov-action@v3 - with: - working-directory: core/packages/contracts - files: lcov.info - flags: solidity diff --git a/.gitignore b/.gitignore index 6dda8766388ef..b384b8879bac0 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ node_modules/ .envrc parachain/build_rs_cov.profraw compiler_config.json +contracts/beefy-state.json + +go/ diff --git a/.gitmodules b/.gitmodules index b510fdaa69bb9..0ec54ebe0f861 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,17 +2,15 @@ path = cumulus url = https://github.com/Snowfork/cumulus branch = snowbridge -[submodule "core/packages/contracts/lib/forge-std"] - path = core/packages/contracts/lib/forge-std +[submodule "contracts/lib/forge-std"] + path = contracts/lib/forge-std url = https://github.com/foundry-rs/forge-std - branch = master -[submodule "core/packages/contracts/lib/ds-test"] - path = core/packages/contracts/lib/ds-test +[submodule "contracts/lib/openzeppelin-contracts"] + path = contracts/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "contracts/lib/ds-test"] + path = contracts/lib/ds-test url = https://github.com/dapphub/ds-test -[submodule "core/packages/contracts/lib/openzeppelin-contracts"] - path = core/packages/contracts/lib/openzeppelin-contracts - url = https://github.com/openzeppelin/openzeppelin-contracts - branch = v4.8.2 -[submodule "core/packages/contracts/lib/canonical-weth"] - path = core/packages/contracts/lib/canonical-weth - url = https://github.com/snowfork/canonical-weth +[submodule "contracts/lib/canonical-weth"] + path = contracts/lib/canonical-weth + url = https://github.com/Snowfork/canonical-weth diff --git a/README.md b/README.md index f1b9cfc7a6d0c..b46da19aac2b0 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ Off-chain relayer services for relaying messages between Polkadot and Ethereum. ### Contracts -Ethereum contracts and unit tests. See [core/packages/contracts/README.md](core/packages/contracts/README.md) +Ethereum contracts and unit tests. See [contracts/README.md](contracts/README.md) ### Integration Tests -This component includes our end to end tests, that pull together all the above services and set them up easily through scripts for automated E2E tests. See [core/packages/test/README.md](core/packages/test/README.md). +This component includes our end to end tests, that pull together all the above services and set them up easily through scripts for automated E2E tests. See [web/packages/test/README.md](web/packages/test/README.md). ## Development @@ -31,15 +31,19 @@ mkdir -p ~/.config/nix echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf ``` -(if you don't want to use flakes, you can instead pass the flag `--experimental-features nix-command flakes` to nix, eg. -`nix --experimental-features 'nix-command flakes' develop`) - Then activate a developer shell in the root of our repo, where [`flake.nix`](./flake.nix) is located: ```sh nix develop ``` +Also make sure to run this initialization script once: +```sh +scripts/init.sh +``` + +### Support for code editors + To ensure your code editor (such as VS Code) can execute tools in the nix shell, startup your editor within the interactive shell. @@ -50,21 +54,25 @@ nix develop code . ``` +### Custom shells + The developer shell is bash by default. To preserve your existing shell: ```sh nix develop --command $SHELL ``` +### Automatic developer shells + To automatically enter the developer shell whenever you open the project, install [`direnv`](https://direnv.net/docs/installation.html) and use the template `.envrc`: ```sh cp .envrc.example .envrc direnv allow -```` +``` -## Upgrade +### Upgrading the Rust toolchain Sometimes we would like to upgrade rust toolchain. First update `parachain/rust-toolchain.toml` as required and then update `flake.lock` running ```sh diff --git a/_typos.toml b/_typos.toml index ecf3bd7005d77..b7fd8c6b7b7a7 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1,6 +1,6 @@ [files] extend-exclude = [ - "core/packages/contracts/lib", + "contracts/lib", "**/*.yaml", "**/*.json", "**/fixtures/*.js", diff --git a/codecov.yml b/codecov.yml index c48e00a9166e4..04f3d1099dd38 100644 --- a/codecov.yml +++ b/codecov.yml @@ -5,18 +5,18 @@ coverage: github_checks: annotations: false ignore: - - "core/packages/contracts/test/mocks" - - "core/packages/contracts/src/utils" - - "core/packages/contracts/src/ScaleCodec.sol" - - "core/packages/contracts/src/SubstrateTypes.sol" + - "contracts/test/mocks" + - "contracts/src/utils" + - "contracts/src/ScaleCodec.sol" + - "contracts/src/SubstrateTypes.sol" - "parachain/tools" - "parachain/pallets/ethereum-beacon-client/src/benchmarking" - "parachain/pallets/ethereum-beacon-client/src/weights.rs" - - "core/packages/contracts/src/DeployScript.sol" + - "contracts/src/DeployScript.sol" flags: solidity: paths: - - core/packages/contracts + - contracts carryforward: true rust: paths: diff --git a/core/packages/contracts/.editorconfig b/contracts/.editorconfig similarity index 100% rename from core/packages/contracts/.editorconfig rename to contracts/.editorconfig diff --git a/core/packages/contracts/.envrc-example b/contracts/.envrc-example similarity index 88% rename from core/packages/contracts/.envrc-example rename to contracts/.envrc-example index a20809074f305..71b29aa61f8d2 100644 --- a/core/packages/contracts/.envrc-example +++ b/contracts/.envrc-example @@ -5,6 +5,8 @@ source_up_if_exists ## BeefyClient export RANDAO_COMMIT_DELAY=3 export RANDAO_COMMIT_EXP=8 +export PREV_RANDAO=377 +export ValidatorSetSize=300 ## ParachainClient export PARAID=1000 diff --git a/contracts/.gas-snapshot b/contracts/.gas-snapshot new file mode 100644 index 0000000000000..9a7eb4ef603c8 --- /dev/null +++ b/contracts/.gas-snapshot @@ -0,0 +1,70 @@ +AgentTest:testInvoke() (gas: 20810) +AgentTest:testInvokeFail() (gas: 13429) +AgentTest:testInvokeUnauthorized() (gas: 13974) +BeefyClientTest:testCreateFinalBitfield() (gas: 278225) +BeefyClientTest:testCreateFinalBitfieldInvalid() (gas: 265008) +BeefyClientTest:testCreateInitialBitfield() (gas: 650507) +BeefyClientTest:testCreateInitialBitfieldInvalid() (gas: 578841) +BeefyClientTest:testScaleEncodeCommit() (gas: 32353) +BeefyClientTest:testSubmit():((uint32,uint64,(bytes2,bytes)[])) (gas: 708627) +BeefyClientTest:testSubmitFailForPrevRandaoCapturedMoreThanOnce() (gas: 266184) +BeefyClientTest:testSubmitFailForPrevRandaoTooEarlyOrTooLate() (gas: 207388) +BeefyClientTest:testSubmitFailInvalidSignature() (gas: 657123) +BeefyClientTest:testSubmitFailValidatorNotInBitfield() (gas: 645077) +BeefyClientTest:testSubmitFailWithInvalidBitfield() (gas: 634383) +BeefyClientTest:testSubmitFailWithInvalidMMRLeaf() (gas: 748779) +BeefyClientTest:testSubmitFailWithInvalidMMRLeafProof() (gas: 752764) +BeefyClientTest:testSubmitFailWithInvalidTicket() (gas: 638107) +BeefyClientTest:testSubmitFailWithInvalidValidatorSet() (gas: 642432) +BeefyClientTest:testSubmitFailWithNotEnoughClaims() (gas: 197586) +BeefyClientTest:testSubmitFailWithStaleCommitment() (gas: 835952) +BeefyClientTest:testSubmitFailWithoutPrevRandao() (gas: 532261) +BeefyClientTest:testSubmitWithHandover() (gas: 736139) +BeefyClientTest:testSubmitWithHandoverFailStaleCommitment() (gas: 859922) +BeefyClientTest:testSubmitWithHandoverFailWithInvalidValidatorSet() (gas: 666242) +BeefyClientTest:testSubmitWithHandoverFailWithoutPrevRandao() (gas: 556301) +GatewayTest:testAgentExecution() (gas: 52791) +GatewayTest:testAgentExecutionBadOrigin() (gas: 23354) +GatewayTest:testAgentExecutionBadPayload() (gas: 22077) +GatewayTest:testCreateAgent() (gas: 254909) +GatewayTest:testCreateAgentAlreadyCreated() (gas: 256489) +GatewayTest:testCreateChannel() (gas: 332117) +GatewayTest:testCreateChannelFailsAgentDoesNotExist() (gas: 19185) +GatewayTest:testCreateChannelFailsChannelAlreadyExists() (gas: 335995) +GatewayTest:testDisableOutboundMessaging() (gas: 67040) +GatewayTest:testDisableOutboundMessagingForChannel() (gas: 161374) +GatewayTest:testGetters() (gas: 37883) +GatewayTest:testHandlersNotExternallyCallable() (gas: 52292) +GatewayTest:testInitializeNotExternallyCallable() (gas: 16762) +GatewayTest:testRegisterToken() (gas: 85845) +GatewayTest:testRelayerNotRewarded() (gas: 75289) +GatewayTest:testRelayerRewardedFromAgent() (gas: 310728) +GatewayTest:testSendTokenAddress20() (gas: 128049) +GatewayTest:testSendTokenAddress20FailsInvalidDestination() (gas: 59703) +GatewayTest:testSendTokenAddress32() (gas: 129387) +GatewayTest:testSendTokenAddress32ToAssetHub() (gas: 128776) +GatewayTest:testSetOperatingMode() (gas: 39208) +GatewayTest:testSubmitFailInvalidChannel() (gas: 27926) +GatewayTest:testSubmitFailInvalidNonce() (gas: 318948) +GatewayTest:testSubmitHappyPath() (gas: 312342) +GatewayTest:testUpdateChannel() (gas: 58121) +GatewayTest:testUpdateChannelFailDoesNotExist() (gas: 20107) +GatewayTest:testUpdateChannelSanityChecksForBridgeHubChannel() (gas: 22147) +GatewayTest:testUpgrade() (gas: 208455) +GatewayTest:testUpgradeFailCodeHashMismatch() (gas: 178843) +GatewayTest:testUpgradeFailOnInitializationFailure() (gas: 182568) +GatewayTest:testUserDoesNotProvideEnoughFees() (gas: 218463) +GatewayTest:testUserPaysFees() (gas: 244678) +GatewayTest:testWithdrawAgentFunds() (gas: 64315) +MMRProofTest:testVerifyLeafProof() (gas: 370749) +MMRProofTest:testVerifyLeafProofFailsExceededProofSize() (gas: 358741) +ScaleCodecTest:testCheckedEncodeCompactU32() (gas: 5120) +ScaleCodecTest:testEncodeCompactU32() (gas: 9722) +ScaleCodecTest:testEncodeU128() (gas: 192) +ScaleCodecTest:testEncodeU16() (gas: 434) +ScaleCodecTest:testEncodeU256() (gas: 478) +ScaleCodecTest:testEncodeU32() (gas: 170) +ScaleCodecTest:testEncodeU64() (gas: 280) +VerificationTest:testCreateParachainHeaderMerkleFailInvalidHeader() (gas: 11341) +VerificationTest:testCreateParachainHeaderMerkleLeaf() (gas: 20830) +VerificationTest:testIsCommitmentInHeaderDigest() (gas: 21863) \ No newline at end of file diff --git a/core/packages/contracts/.gitignore b/contracts/.gitignore similarity index 96% rename from core/packages/contracts/.gitignore rename to contracts/.gitignore index 7fdb56d03ad6e..e8048ec912e16 100644 --- a/core/packages/contracts/.gitignore +++ b/contracts/.gitignore @@ -16,3 +16,4 @@ types/ tsconfig.tsbuildinfo lcov.info tenderly.yaml +docs/ diff --git a/core/packages/contracts/LICENSE b/contracts/LICENSE similarity index 100% rename from core/packages/contracts/LICENSE rename to contracts/LICENSE diff --git a/contracts/README.md b/contracts/README.md new file mode 100644 index 0000000000000..9174cb5b8b6c1 --- /dev/null +++ b/contracts/README.md @@ -0,0 +1,71 @@ +# Ethereum Contracts + +## Overview + +### Gateway + +The Ethereum side of the bridge is organised around a central `Gateway` contract, responsible for the following: +* Receiving, verifying, and dispatching inbound messages from Polkadot +* Accepting outbound messages for delivery to Polkadot +* Higher-level application features such as token transfers + +The gateway is defined by the following contracts +* [IGateway.sol](src/interfaces/IGateway.sol): Public API of the gateway +* [GatewayProxy.sol](src/Gateway.sol): Proxy contract for the gateway +* [Gateway.sol](src/Gateway.sol): Implementation contract of the gateway + +The gateway is modular in design, being composed of libraries implementing specific functionality: + +* [Verification.sol](src/Verification.sol): Verification of inbound messages from Polakdot +* [Assets.sol](src/Assets.sol): ERC20 token transfers to Polkadot + +#### Governance + +Using cross-chain messaging, the gateway is governed remotely by the governance of the Polkadot relay chain. + +#### Upgrades + +The gateway consists of an upgradable proxy, and an implementation contract, loosely following the [ERC1967](https://eips.ethereum.org/EIPS/eip-1967) standard. + +### Agents + +Agents are proxy contracts for arbitrary consensus systems on Polkadot. Logically, one can think of them as the sovereign accounts of remote consensus systems. + +They have a number of uses: +* When an Ethereum user sends ERC20 tokens to Polkadot (Specifically the AssetHub parachain), these tokens are actually locked into the agent contract corresponding to the AssetHub parachain. Then finally, on the AssetHub parachain, wrapped tokens are minted into an account controlled by the sender. +* When a Polkadot parachain wishes to call a function on an Ethereum contract, it will appear to the destination contract that the message sender is the agent contract for the origin parachain. +* Agents control the funds for receiving fees from users and disbursing rewards to message relayers + +Agents are defined by the following contracts: +* [Agent.sol](src/Agent.sol): Agent contract +* [AgentExecutor.sol](src/AgentExecutor.sol): Code executed within an agent using `delegatecall` + +The creation of new agents can be initiated by calling `EthereumControl::create_agent` extrinsic on the BridgeHub parachain. + +### BeefyClient + +The [BeefyClient.sol](src/BeefyClient.sol) contract implements a light client for following a subset of Polkadot consensus. In conjunction with the [Verification.sol](src/Verification.sol) library, it used to verify inbound messages from the BridgeHub parachain. + +## Testing + +Run all tests: + +```bash +forge test +``` + +Run coverage reports: + +```bash +forge coverage +``` + +## Test Fixtures + +Some of the unit tests require fixture data generated by a live deployment. For this purpose, we use logging artifacts from the offchain relayers running in the [E2E](../web/packages/test) stack. +``` + +BEEFY commitments & proofs extracted from `/tmp/snowbridge/beefy-relay.log`. + +1. Search for `Sent SubmitFinal transaction` in relayer log file +2. Copy into `test/data/beefy-commitment.json` diff --git a/core/packages/contracts/foundry.toml b/contracts/foundry.toml similarity index 57% rename from core/packages/contracts/foundry.toml rename to contracts/foundry.toml index 0d43c12fd05c8..4b22198d96bda 100644 --- a/core/packages/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -4,9 +4,11 @@ optimizer = true optimizer_runs = 20_000 via_ir = true test = 'test' -ffi = true +fs_permissions = [{ access = "read-write", path = "test/data"}, { access = "read", path = "./"}] ignored_error_codes = [ # DeployScript.sol is never deployed 5574 ] + +# no_match_test = "testRegenerateBitField" diff --git a/core/packages/contracts/lib/canonical-weth b/contracts/lib/canonical-weth similarity index 100% rename from core/packages/contracts/lib/canonical-weth rename to contracts/lib/canonical-weth diff --git a/core/packages/contracts/lib/ds-test b/contracts/lib/ds-test similarity index 100% rename from core/packages/contracts/lib/ds-test rename to contracts/lib/ds-test diff --git a/contracts/lib/forge-std b/contracts/lib/forge-std new file mode 160000 index 0000000000000..74cfb77e308dd --- /dev/null +++ b/contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 74cfb77e308dd188d2f58864aaf44963ae6b88b1 diff --git a/contracts/lib/openzeppelin-contracts b/contracts/lib/openzeppelin-contracts new file mode 160000 index 0000000000000..e50c24f5839db --- /dev/null +++ b/contracts/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit e50c24f5839db17f46991478384bfda14acfb830 diff --git a/core/packages/contracts/remappings.txt b/contracts/remappings.txt similarity index 100% rename from core/packages/contracts/remappings.txt rename to contracts/remappings.txt diff --git a/core/packages/contracts/scripts/minsigs.py b/contracts/scripts/minsigs.py similarity index 100% rename from core/packages/contracts/scripts/minsigs.py rename to contracts/scripts/minsigs.py diff --git a/contracts/src/Agent.sol b/contracts/src/Agent.sol new file mode 100644 index 0000000000000..fedaa5d972f88 --- /dev/null +++ b/contracts/src/Agent.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +/// @title An agent contract that acts on behalf of a consensus system on Polkadot +/// @dev Instances of this contract act as an agents for arbitrary consensus systems on Polkadot. These consensus systems +/// can include toplevel parachains as as well as nested consensus systems within a parachain. +contract Agent { + error Unauthorized(); + + /// @dev The unique ID for this agent, derived from the MultiLocation of the corresponding consensus system on Polkadot + bytes32 public immutable AGENT_ID; + + /// @dev The gateway contract controlling this agent + address public immutable GATEWAY; + + constructor(bytes32 agentID) { + AGENT_ID = agentID; + GATEWAY = msg.sender; + } + + /// @dev Agents can receive ether permissionlessly. + /// This is important, as agents for top-level parachains also act as sovereign accounts from which message relayers + /// are rewarded. + receive() external payable {} + + /// @dev Allow the gateway to invoke some code within the context of this agent + /// using `delegatecall`. Typically this code will be provided by `AgentExecutor.sol`. + function invoke(address executor, bytes calldata data) external returns (bool, bytes memory) { + if (msg.sender != GATEWAY) { + revert Unauthorized(); + } + return executor.delegatecall(data); + } +} diff --git a/contracts/src/AgentExecutor.sol b/contracts/src/AgentExecutor.sol new file mode 100644 index 0000000000000..488eb4bb9ef21 --- /dev/null +++ b/contracts/src/AgentExecutor.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {AgentExecuteCommand, ParaID} from "./Types.sol"; +import {SubstrateTypes} from "./SubstrateTypes.sol"; + +import {IERC20} from "./interfaces/IERC20.sol"; +import {SafeTokenTransfer, SafeNativeTransfer} from "./utils/SafeTransfer.sol"; + +/// @title Code which will run within an `Agent` using `delegatecall`. +/// @dev This is a singleton contract, meaning that all agents will execute the same code. +contract AgentExecutor { + using SafeTokenTransfer for IERC20; + using SafeNativeTransfer for address payable; + + /// @dev Execute a message which originated from the Polkadot side of the bridge. In other terms, + /// the `data` parameter is constructed by the BridgeHub parachain. + /// + /// NOTE: There are no authorization checks here. Since this contract is only used for its code. + function execute(address, bytes memory data) external { + (AgentExecuteCommand command, bytes memory params) = abi.decode(data, (AgentExecuteCommand, bytes)); + if (command == AgentExecuteCommand.TransferToken) { + (address token, address recipient, uint128 amount) = abi.decode(params, (address, address, uint128)); + _transferToken(token, recipient, amount); + } + } + + /// @dev Transfer ether to `recipient`. Unlike `_transferToken` This logic is not nested within `execute`, + /// as the gateway needs to control an agent's ether balance directly. + /// + /// NOTE: There are no authorization checks here. Since this contract is only used for its code. + function transferNative(address payable recipient, uint256 amount) external { + recipient.safeNativeTransfer(amount); + } + + /// @dev Transfer ERC20 to `recipient`. Only callable via `execute`. + function _transferToken(address token, address recipient, uint128 amount) internal { + IERC20(token).safeTransfer(recipient, amount); + } +} diff --git a/contracts/src/Assets.sol b/contracts/src/Assets.sol new file mode 100644 index 0000000000000..5fe9402e83bf2 --- /dev/null +++ b/contracts/src/Assets.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {IERC20} from "./interfaces/IERC20.sol"; +import {IGateway} from "./interfaces/IGateway.sol"; + +import {SafeTokenTransferFrom} from "./utils/SafeTransfer.sol"; + +import {AssetsStorage} from "./storage/AssetsStorage.sol"; +import {SubstrateTypes} from "./SubstrateTypes.sol"; +import {ParaID, Config} from "./Types.sol"; +import {Address} from "./utils/Address.sol"; + +/// @title Library for implementing Ethereum->Polkadot ERC20 transfers. +library Assets { + using Address for address; + using SafeTokenTransferFrom for IERC20; + + /// @dev Emitted once the funds are locked and a message is successfully queued. + event TokenSent( + address indexed token, address indexed sender, ParaID destinationChain, bytes destinationAddress, uint128 amount + ); + event TokenRegistrationSent(address token); + + /* Errors */ + error InvalidToken(); + error InvalidAmount(); + error InvalidDestination(); + + // This library requires state which must be initialized in the gateway's storage. + function initialize(uint256 registerTokenFee, uint256 sendTokenFee) external { + AssetsStorage.Layout storage $ = AssetsStorage.layout(); + + $.registerTokenFee = registerTokenFee; + $.sendTokenFee = sendTokenFee; + } + + function sendToken( + ParaID assetHubParaID, + address assetHubAgent, + address token, + address sender, + ParaID destinationChain, + bytes32 destinationAddress, + uint128 amount + ) external returns (bytes memory payload, uint256 extraFee) { + AssetsStorage.Layout storage $ = AssetsStorage.layout(); + + _transferToAgent(assetHubAgent, token, sender, amount); + if (destinationChain == assetHubParaID) { + payload = SubstrateTypes.SendToken(address(this), token, destinationAddress, amount); + } else { + payload = SubstrateTypes.SendToken(address(this), token, destinationChain, destinationAddress, amount); + } + extraFee = $.sendTokenFee; + + emit TokenSent(sender, token, destinationChain, abi.encodePacked(destinationAddress), amount); + } + + function sendToken( + ParaID assetHubParaID, + address assetHubAgent, + address token, + address sender, + ParaID destinationChain, + address destinationAddress, + uint128 amount + ) external returns (bytes memory payload, uint256 extraFee) { + AssetsStorage.Layout storage $ = AssetsStorage.layout(); + if (destinationChain == assetHubParaID) { + // AssetHub parachain doesn't support Ethereum-style addresses + revert InvalidDestination(); + } + + _transferToAgent(assetHubAgent, token, sender, amount); + + payload = SubstrateTypes.SendToken(address(this), token, destinationChain, destinationAddress, amount); + extraFee = $.sendTokenFee; + emit TokenSent(sender, token, destinationChain, abi.encodePacked(destinationAddress), amount); + } + + /// @dev transfer tokens from the sender to the specified + function _transferToAgent(address assetHubAgent, address token, address sender, uint128 amount) internal { + if (!token.isContract()) { + revert InvalidToken(); + } + + if (amount == 0) { + revert InvalidAmount(); + } + + IERC20(token).safeTransferFrom(sender, assetHubAgent, amount); + } + + /// @dev Enqueues a create native token message to substrate. + /// @param token The ERC20 token address. + function registerToken(address token, bytes2 createTokenCallID) + external + returns (bytes memory payload, uint256 extraFee) + { + AssetsStorage.Layout storage $ = AssetsStorage.layout(); + + if (!token.isContract()) { + revert InvalidToken(); + } + + payload = SubstrateTypes.RegisterToken(address(this), token, createTokenCallID); + extraFee = $.registerTokenFee; + + emit TokenRegistrationSent(token); + } +} diff --git a/core/packages/contracts/src/BeefyClient.sol b/contracts/src/BeefyClient.sol similarity index 95% rename from core/packages/contracts/src/BeefyClient.sol rename to contracts/src/BeefyClient.sol index 2b902cd47c66e..71cc78d7c1a29 100644 --- a/core/packages/contracts/src/BeefyClient.sol +++ b/contracts/src/BeefyClient.sol @@ -3,11 +3,10 @@ pragma solidity 0.8.20; import {ECDSA} from "openzeppelin/utils/cryptography/ECDSA.sol"; -import {Ownable} from "openzeppelin/access/Ownable.sol"; -import {MerkleProof} from "./utils/MerkleProof.sol"; +import {SubstrateMerkleProof} from "./utils/SubstrateMerkleProof.sol"; import {Bitfield} from "./utils/Bitfield.sol"; import {MMRProof} from "./utils/MMRProof.sol"; -import {ScaleCodec} from "./ScaleCodec.sol"; +import {ScaleCodec} from "./utils/ScaleCodec.sol"; /** * @title BeefyClient @@ -29,7 +28,7 @@ import {ScaleCodec} from "./ScaleCodec.sol"; * 4. submitFinalWithHandover (with signature proofs specified by (3)) * */ -contract BeefyClient is Ownable { +contract BeefyClient { /* Events */ /** @@ -152,7 +151,7 @@ contract BeefyClient is Ownable { * @dev Beefy payload id for MMR Root payload items: * https://github.com/paritytech/substrate/blob/fe1f8ba1c4f23931ae89c1ada35efb3d908b50f5/primitives/consensus/beefy/src/payload.rs#L33 */ - bytes2 public constant mmrRootID = bytes2("mh"); + bytes2 public constant MMR_ROOT_ID = bytes2("mh"); /** * @dev Minimum delay in number of blocks that a relayer must wait between calling @@ -170,38 +169,35 @@ contract BeefyClient is Ownable { uint256 public immutable randaoCommitExpiration; /* Errors */ + error InvalidBitfield(); + error InvalidBitfieldLength(); error InvalidCommitment(); - error StaleCommitment(); - error InvalidValidatorProof(); - error InvalidSignature(); - error NotEnoughClaims(); error InvalidMMRLeaf(); error InvalidMMRLeafProof(); - error InvalidBitfield(); - error WaitPeriodNotOver(); - error TicketExpired(); - error PrevRandaoAlreadyCaptured(); - error PrevRandaoNotCaptured(); - error InvalidBitfieldLength(); - error InvalidTicket(); error InvalidMMRRootLength(); + error InvalidSignature(); + error InvalidTicket(); + error InvalidValidatorProof(); error NoMMRRootInCommitment(); + error NotEnoughClaims(); + error PrevRandaoAlreadyCaptured(); + error PrevRandaoNotCaptured(); + error StaleCommitment(); + error TicketExpired(); + error WaitPeriodNotOver(); - constructor(uint256 _randaoCommitDelay, uint256 _randaoCommitExpiration) { + constructor( + uint256 _randaoCommitDelay, + uint256 _randaoCommitExpiration, + uint64 _initialBeefyBlock, + ValidatorSet memory _initialValidatorSet, + ValidatorSet memory _nextValidatorSet + ) { randaoCommitDelay = _randaoCommitDelay; randaoCommitExpiration = _randaoCommitExpiration; - } - - // Once-off post-construction call to set initial configuration. - function initialize( - uint64 _initialBeefyBlock, - ValidatorSet calldata _initialValidatorSet, - ValidatorSet calldata _nextValidatorSet - ) external onlyOwner { latestBeefyBlock = _initialBeefyBlock; currentValidatorSet = _initialValidatorSet; nextValidatorSet = _nextValidatorSet; - renounceOwnership(); } /* Public Functions */ @@ -244,6 +240,10 @@ contract BeefyClient is Ownable { revert InvalidValidatorProof(); } + if (commitment.validatorSetID != vset.id) { + revert InvalidCommitment(); + } + // Check if validatorSignature is correct, ie. check if it matches // the signature of senderPublicKey on the commitmentHash bytes32 commitmentHash = keccak256(encodeCommitment(commitment)); @@ -515,7 +515,7 @@ contract BeefyClient is Ownable { function getFirstMMRRoot(Commitment calldata commitment) internal pure returns (bytes32) { for (uint256 i = 0; i < commitment.payload.length; i++) { - if (commitment.payload[i].payloadID == mmrRootID) { + if (commitment.payload[i].payloadID == MMR_ROOT_ID) { if (commitment.payload[i].data.length != 32) { revert InvalidMMRRootLength(); } else { @@ -536,10 +536,13 @@ contract BeefyClient is Ownable { } function encodeCommitmentPayload(PayloadItem[] calldata items) internal pure returns (bytes memory) { - bytes memory payload = ScaleCodec.encodeCompactUint(items.length); + bytes memory payload = ScaleCodec.checkedEncodeCompactU32(uint32(items.length)); for (uint256 i = 0; i < items.length; i++) { payload = bytes.concat( - payload, items[i].payloadID, ScaleCodec.encodeCompactUint(items[i].data.length), items[i].data + payload, + items[i].payloadID, + ScaleCodec.checkedEncodeCompactU32(uint32(items[i].data.length)), + items[i].data ); } @@ -578,7 +581,7 @@ contract BeefyClient is Ownable { returns (bool) { bytes32 hashedLeaf = keccak256(abi.encodePacked(account)); - return MerkleProof.verify(vset.root, hashedLeaf, index, vset.length, proof); + return SubstrateMerkleProof.verify(vset.root, hashedLeaf, index, vset.length, proof); } // Basic checks for commitment @@ -592,6 +595,7 @@ contract BeefyClient is Ownable { Ticket storage ticket = tickets[ticketID]; if (ticket.blockNumber == 0) { + // Zero value ticket: submitInitial hasn't run for this commitment revert InvalidTicket(); } diff --git a/contracts/src/DeployScript.sol b/contracts/src/DeployScript.sol new file mode 100644 index 0000000000000..7cdb29abdb388 --- /dev/null +++ b/contracts/src/DeployScript.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {WETH9} from "canonical-weth/WETH9.sol"; +import {Script} from "forge-std/Script.sol"; +import {BeefyClient} from "./BeefyClient.sol"; + +import {IGateway} from "./interfaces/IGateway.sol"; +import {GatewayProxy} from "./GatewayProxy.sol"; +import {Gateway} from "./Gateway.sol"; +import {Agent} from "./Agent.sol"; +import {AgentExecutor} from "./AgentExecutor.sol"; +import {ParaID, Config} from "./Types.sol"; +import {SafeNativeTransfer} from "./utils/SafeTransfer.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +contract DeployScript is Script { + using SafeNativeTransfer for address payable; + using stdJson for string; + + function setUp() public {} + + function run() public { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.rememberKey(privateKey); + vm.startBroadcast(deployer); + + // BeefyClient + // Seems `fs_permissions` explicitly configured as absolute path does not work and only allowed from project root + string memory root = vm.projectRoot(); + string memory beefyCheckpointFile = string.concat(root, "/beefy-state.json"); + string memory beefyCheckpointRaw = vm.readFile(beefyCheckpointFile); + uint64 startBlock = uint64(beefyCheckpointRaw.readUint(".startBlock")); + bytes memory currentRaw = beefyCheckpointRaw.parseRaw(".current"); + BeefyClient.ValidatorSet memory current = abi.decode(currentRaw, (BeefyClient.ValidatorSet)); + bytes memory nextRaw = beefyCheckpointRaw.parseRaw(".next"); + BeefyClient.ValidatorSet memory next = abi.decode(nextRaw, (BeefyClient.ValidatorSet)); + uint256 randaoCommitDelay = vm.envUint("RANDAO_COMMIT_DELAY"); + uint256 randaoCommitExpiration = vm.envUint("RANDAO_COMMIT_EXP"); + BeefyClient beefyClient = new BeefyClient(randaoCommitDelay, randaoCommitExpiration, startBlock, current, next); + + ParaID bridgeHubParaID = ParaID.wrap(vm.envUint("BRIDGE_HUB_PARAID")); + bytes32 bridgeHubAgentID = vm.envBytes32("BRIDGE_HUB_AGENT_ID"); + ParaID assetHubParaID = ParaID.wrap(vm.envUint("ASSET_HUB_PARAID")); + bytes32 assetHubAgentID = vm.envBytes32("ASSET_HUB_AGENT_ID"); + + AgentExecutor executor = new AgentExecutor(); + Gateway gatewayLogic = new Gateway( + address(beefyClient), + address(executor), + vm.envUint("DISPATCH_GAS"), + bridgeHubParaID, + bridgeHubAgentID, + assetHubParaID, + assetHubAgentID, + bytes2(vm.envBytes("CREATE_CALL_INDEX")) + ); + + bytes memory initParams = abi.encode( + vm.envUint("DEFAULT_FEE"), + vm.envUint("DEFAULT_REWARD"), + vm.envUint("REGISTER_NATIVE_TOKEN_FEE"), + vm.envUint("SEND_NATIVE_TOKEN_FEE") + ); + + GatewayProxy gateway = new GatewayProxy(address(gatewayLogic), initParams); + + // Deploy WETH for testing + new WETH9(); + + // Fund the sovereign account for the BridgeHub parachain. Used to reward relayers + // of messages originating from BridgeHub + uint256 initialDeposit = vm.envUint("BRIDGE_HUB_INITIAL_DEPOSIT"); + + address bridgeHubAgent = IGateway(address(gateway)).agentOf(bridgeHubAgentID); + address assetHubAgent = IGateway(address(gateway)).agentOf(assetHubAgentID); + + payable(bridgeHubAgent).safeNativeTransfer(initialDeposit); + payable(assetHubAgent).safeNativeTransfer(initialDeposit); + + vm.stopBroadcast(); + } +} diff --git a/contracts/src/Gateway.sol b/contracts/src/Gateway.sol new file mode 100644 index 0000000000000..315e3c0797015 --- /dev/null +++ b/contracts/src/Gateway.sol @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {MerkleProof} from "openzeppelin/utils/cryptography/MerkleProof.sol"; +import {Verification} from "./Verification.sol"; + +import {Assets} from "./Assets.sol"; +import {AgentExecutor} from "./AgentExecutor.sol"; +import {Agent} from "./Agent.sol"; +import {Channel, InboundMessage, OperatingMode, ParaID, Config, Command} from "./Types.sol"; +import {IGateway} from "./interfaces/IGateway.sol"; +import {IInitializable} from "./interfaces/IInitializable.sol"; +import {ERC1967} from "./utils/ERC1967.sol"; +import {Address} from "./utils/Address.sol"; +import {SafeNativeTransfer} from "./utils/SafeTransfer.sol"; +import {Call} from "./utils/Call.sol"; +import {ScaleCodec} from "./utils/ScaleCodec.sol"; + +import {CoreStorage} from "./storage/CoreStorage.sol"; +import {AssetsStorage} from "./storage/AssetsStorage.sol"; + +contract Gateway is IGateway, IInitializable { + using Address for address; + using SafeNativeTransfer for address payable; + + // After message dispatch, there should be some gas left over for post dispatch logic + uint256 internal constant BUFFER_GAS = 32_000; + uint256 internal immutable DISPATCH_GAS; + address internal immutable AGENT_EXECUTOR; + + // Verification state + address internal immutable BEEFY_CLIENT; + + // BridgeHub + ParaID internal immutable BRIDGE_HUB_PARA_ID; + bytes4 internal immutable BRIDGE_HUB_PARA_ID_ENCODED; + bytes32 internal immutable BRIDGE_HUB_AGENT_ID; + + // AssetHub + ParaID internal immutable ASSET_HUB_PARA_ID; + bytes32 internal immutable ASSET_HUB_AGENT_ID; + bytes2 internal immutable CREATE_TOKEN_CALL_ID; + + error InvalidProof(); + error InvalidNonce(); + error InvalidAgentExecutor(); + error NotEnoughGas(); + error FeePaymentToLow(); + error FailedPayment(); + error Unauthorized(); + error UnknownChannel(); + error Disabled(); + error AgentAlreadyCreated(); + error AgentDoesNotExist(); + error ChannelAlreadyCreated(); + error ChannelDoesNotExist(); + error InvalidChannelUpdate(); + error WithdrawalFailed(); + error AgentExecutionFailed(bytes returndata); + error InvalidAgentExecutionPayload(); + error InvalidConfig(); + error NotProxy(); + error InvalidCodeHash(); + + // handler functions are privileged + modifier onlySelf() { + if (msg.sender != address(this)) { + revert Unauthorized(); + } + _; + } + + constructor( + address beefyClient, + address agentExecutor, + uint256 dispatchGas, + ParaID bridgeHubParaID, + bytes32 bridgeHubHubAgentID, + ParaID assetHubParaID, + bytes32 assetHubHubAgentID, + bytes2 createTokenCallID + ) { + BEEFY_CLIENT = beefyClient; + AGENT_EXECUTOR = agentExecutor; + DISPATCH_GAS = dispatchGas; + BRIDGE_HUB_PARA_ID_ENCODED = ScaleCodec.encodeU32(uint32(ParaID.unwrap(bridgeHubParaID))); + BRIDGE_HUB_PARA_ID = bridgeHubParaID; + BRIDGE_HUB_AGENT_ID = bridgeHubHubAgentID; + ASSET_HUB_PARA_ID = assetHubParaID; + ASSET_HUB_AGENT_ID = assetHubHubAgentID; + CREATE_TOKEN_CALL_ID = createTokenCallID; + } + + /// @dev Submit a message from Polkadot for verification and dispatch + /// @param message A message produced by the OutboundQueue pallet on BridgeHub + /// @param leafProof A message proof used to verify that the message is in the merkle tree committed by the OutboundQueue pallet + /// @param headerProof A proof used to verify that the commitment was included in a BridgeHub header that was finalized by BEEFY. + function submitInbound( + InboundMessage calldata message, + bytes32[] calldata leafProof, + Verification.Proof calldata headerProof + ) external { + Channel storage channel = _ensureChannel(message.origin); + + // Produce the commitment (message root) by applying the leaf proof to the message leaf + bytes32 leafHash = keccak256(abi.encode(message)); + bytes32 commitment = MerkleProof.processProof(leafProof, leafHash); + + // Verify that the commitment is included in a parachain header finalized by BEEFY. + if (!verifyCommitment(commitment, headerProof)) { + revert InvalidProof(); + } + + // Ensure this message is not being replayed + if (message.nonce != channel.inboundNonce + 1) { + revert InvalidNonce(); + } + + // Increment nonce for origin. + // This also prevents the re-entrancy case in which a malicous party tries to re-enter by calling `submitInbound` + // again with the same (message, leafProof, headerProof) arguments. + channel.inboundNonce++; + + // Reward the relayer from the agent contract + // Expected to revert if the agent for the message origin does not have enough funds to reward the relayer. + // In that case, the origin should top up the funds of their agent. + if (channel.reward > 0) { + _transferNativeFromAgent(channel.agent, payable(msg.sender), channel.reward); + } + + // Ensure relayers pass enough gas for message to execute. + // Otherwise malicious relayers can break the bridge by allowing the message handlers below to run out gas and fail silently. + // In this scenario case, the channel's state would have been updated to accept the message (by virtue of the nonce increment), yet the actual message + // dispatch would have failed + if (gasleft() < DISPATCH_GAS + BUFFER_GAS) { + revert NotEnoughGas(); + } + + bool success = true; + + // Dispatch message to a handler + if (message.command == Command.AgentExecute) { + try Gateway(this).agentExecute{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } else if (message.command == Command.CreateAgent) { + try Gateway(this).createAgent{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } else if (message.command == Command.CreateChannel) { + try Gateway(this).createChannel{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } else if (message.command == Command.UpdateChannel) { + try Gateway(this).updateChannel{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } else if (message.command == Command.SetOperatingMode) { + try Gateway(this).setOperatingMode{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } else if (message.command == Command.TransferNativeFromAgent) { + try Gateway(this).transferNativeFromAgent{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } else if (message.command == Command.Upgrade) { + try Gateway(this).upgrade{gas: DISPATCH_GAS}(message.params) {} + catch { + success = false; + } + } + + emit IGateway.InboundMessageDispatched(message.origin, message.nonce, success); + } + + /** + * Getters + */ + + function operatingMode() external view returns (OperatingMode) { + return CoreStorage.layout().mode; + } + + function channelOperatingModeOf(ParaID paraID) external view returns (OperatingMode) { + CoreStorage.Layout storage $ = CoreStorage.layout(); + return $.channels[paraID].mode; + } + + function channelNoncesOf(ParaID paraID) external view returns (uint64, uint64) { + Channel storage ch = CoreStorage.layout().channels[paraID]; + return (ch.inboundNonce, ch.outboundNonce); + } + + function channelFeeRewardOf(ParaID paraID) external view returns (uint256, uint256) { + Channel storage ch = CoreStorage.layout().channels[paraID]; + return (ch.fee, ch.reward); + } + + function agentOf(bytes32 agentID) external view returns (address) { + CoreStorage.Layout storage $ = CoreStorage.layout(); + return $.agents[agentID]; + } + + function implementation() public view returns (address) { + return ERC1967.load(); + } + + /** + * Handlers + */ + + struct AgentExecuteParams { + bytes32 agentID; + bytes payload; + } + + // Execute code within an agent + function agentExecute(bytes calldata data) external onlySelf { + CoreStorage.Layout storage $ = CoreStorage.layout(); + + AgentExecuteParams memory params = abi.decode(data, (AgentExecuteParams)); + + address agent = $.agents[params.agentID]; + if (agent == address(0)) { + revert AgentDoesNotExist(); + } + + if (params.payload.length == 0) { + revert InvalidAgentExecutionPayload(); + } + + bytes memory call = abi.encodeCall(AgentExecutor.execute, (address(this), params.payload)); + + (bool success, bytes memory returndata) = Agent(payable(agent)).invoke(AGENT_EXECUTOR, call); + if (!success) { + revert AgentExecutionFailed(returndata); + } + } + + struct CreateAgentParams { + /// @dev The agent ID of the consensus system + bytes32 agentID; + } + + /// @dev Create an agent for a consensus system on Polkadot + function createAgent(bytes calldata data) external onlySelf { + CoreStorage.Layout storage $ = CoreStorage.layout(); + + CreateAgentParams memory params = abi.decode(data, (CreateAgentParams)); + + // Ensure we don't overwrite an existing agent + if (address($.agents[params.agentID]) != address(0)) { + revert AgentAlreadyCreated(); + } + + address payable agent = payable(new Agent(params.agentID)); + $.agents[params.agentID] = agent; + + emit AgentCreated(params.agentID, agent); + } + + struct CreateChannelParams { + /// @dev The parachain which will own the newly created channel + ParaID paraID; + /// @dev The agent ID of the parachain + bytes32 agentID; + } + + /// @dev Create a messaging channel for a Polkadot parachain + function createChannel(bytes calldata data) external onlySelf { + CoreStorage.Layout storage $ = CoreStorage.layout(); + + CreateChannelParams memory params = abi.decode(data, (CreateChannelParams)); + + // Ensure that specified agent actually exists + address agent = $.agents[params.agentID]; + if (agent == address(0)) { + revert AgentDoesNotExist(); + } + + // Ensure channel has not already been created + Channel storage ch = $.channels[params.paraID]; + if (address(ch.agent) != address(0)) { + revert ChannelAlreadyCreated(); + } + + ch.mode = OperatingMode.Normal; + ch.agent = $.agents[params.agentID]; + ch.inboundNonce = 0; + ch.outboundNonce = 0; + ch.fee = $.defaultFee; + ch.reward = $.defaultReward; + + emit ChannelCreated(params.paraID); + } + + struct UpdateChannelParams { + /// @dev The parachain used to identify the channel to update + ParaID paraID; + /// @dev The new operating mode + OperatingMode mode; + /// @dev The new fee for accepting outbound messages + uint256 fee; + /// @dev The new reward to be given to relayers for submitting inbound messages + uint256 reward; + } + + /// @dev Update the configuration for a channel + function updateChannel(bytes calldata data) external onlySelf { + UpdateChannelParams memory params = abi.decode(data, (UpdateChannelParams)); + + Channel storage ch = _ensureChannel(params.paraID); + + // Extra sanity checks when updating the BridgeHub channel. For example, a huge reward could + // effectively brick the bridge permanently. + if ( + params.paraID == BRIDGE_HUB_PARA_ID + && (params.mode != OperatingMode.Normal || params.fee > 1 ether || params.reward > 1 ether) + ) { + revert InvalidChannelUpdate(); + } + + ch.mode = params.mode; + ch.fee = params.fee; + ch.reward = params.reward; + + emit ChannelUpdated(params.paraID); + } + + struct UpgradeParams { + /// @dev The address of the implementation contract + address impl; + /// @dev the codehash of the new implementation contract. + /// Used to ensure the implementation isn't updated while + /// the upgrade is in flight + bytes32 implCodeHash; + /// @dev parameters used to upgrade storage of the gateway + bytes initParams; + } + + /// @dev Perform an upgrade of the gateway + function upgrade(bytes calldata data) external onlySelf { + UpgradeParams memory params = abi.decode(data, (UpgradeParams)); + + // Verify that the implementation is actually a contract + if (!params.impl.isContract()) { + revert InvalidCodeHash(); + } + + // Verify that the code in the implementation contract was not changed + // after the upgrade initiated on BridgeHub parachain. + if (params.impl.codehash != params.implCodeHash) { + revert InvalidCodeHash(); + } + + // Update the proxy with the address of the new implementation + ERC1967.store(params.impl); + + // Apply the initialization function of the implementation only if params were provided + if (params.initParams.length > 0) { + (bool success,) = + params.impl.delegatecall(abi.encodeWithSelector(this.initialize.selector, params.initParams)); + if (!success) { + revert InitializationFailed(); + } + } + + emit Upgraded(params.impl); + } + + struct SetOperatingModeParams { + /// @dev The new operating mode + OperatingMode mode; + } + + // @dev Set the operating mode of the gateway + function setOperatingMode(bytes calldata data) external onlySelf { + CoreStorage.Layout storage $ = CoreStorage.layout(); + SetOperatingModeParams memory params = abi.decode(data, (SetOperatingModeParams)); + $.mode = params.mode; + } + + struct TransferNativeFromAgentParams { + /// @dev The ID of the agent to transfer funds from + bytes32 agentID; + /// @dev The recipient of the funds + address recipient; + /// @dev The amount to transfer + uint256 amount; + } + + // @dev Transfer funds from an agent to a recipient account + function transferNativeFromAgent(bytes calldata data) external onlySelf { + CoreStorage.Layout storage $ = CoreStorage.layout(); + + TransferNativeFromAgentParams memory params = abi.decode(data, (TransferNativeFromAgentParams)); + + address agent = $.agents[params.agentID]; + if (agent == address(0)) { + revert AgentDoesNotExist(); + } + + _transferNativeFromAgent(agent, payable(params.recipient), params.amount); + } + + /** + * Assets + */ + + // Register a token on AssetHub + function registerToken(address token) external payable { + (bytes memory payload, uint256 extraFee) = Assets.registerToken(token, CREATE_TOKEN_CALL_ID); + + _submitOutbound(ASSET_HUB_PARA_ID, payload, extraFee); + } + + // Transfer ERC20 tokens to a Polkadot parachain + function sendToken(address token, ParaID destinationChain, bytes32 destinationAddress, uint128 amount) + external + payable + { + CoreStorage.Layout storage $ = CoreStorage.layout(); + address assetHubAgent = $.agents[ASSET_HUB_AGENT_ID]; + + (bytes memory payload, uint256 extraFee) = Assets.sendToken( + ASSET_HUB_PARA_ID, assetHubAgent, token, msg.sender, destinationChain, destinationAddress, amount + ); + + _submitOutbound(ASSET_HUB_PARA_ID, payload, extraFee); + } + + // Transfer ERC20 tokens to a Polkadot parachain + function sendToken(address token, ParaID destinationChain, address destinationAddress, uint128 amount) + external + payable + { + CoreStorage.Layout storage $ = CoreStorage.layout(); + address assetHubAgent = $.agents[ASSET_HUB_AGENT_ID]; + + (bytes memory payload, uint256 extraFee) = Assets.sendToken( + ASSET_HUB_PARA_ID, assetHubAgent, token, msg.sender, destinationChain, destinationAddress, amount + ); + + _submitOutbound(ASSET_HUB_PARA_ID, payload, extraFee); + } + + /* Internal functions */ + + // Verify that a message commitment is considered finalized by our BEEFY light client. + function verifyCommitment(bytes32 commitment, Verification.Proof calldata proof) internal view returns (bool) { + if (BEEFY_CLIENT != address(0)) { + return Verification.verifyCommitment(BEEFY_CLIENT, BRIDGE_HUB_PARA_ID_ENCODED, commitment, proof); + } else { + // for unit tests, verification is bypassed + return true; + } + } + + // Submit an outbound message to Polkadot + function _submitOutbound(ParaID dest, bytes memory payload, uint256 extraFee) internal { + Channel storage channel = _ensureChannel(dest); + + // Ensure outbound messaging is allowed + _ensureOutboundMessagingEnabled(channel); + + // Ensure the user has enough funds for this message to be accepted + if (msg.value < channel.fee + extraFee) { + revert FeePaymentToLow(); + } + + channel.outboundNonce = channel.outboundNonce + 1; + + // Deposit total fee into agent's contract + payable(channel.agent).safeNativeTransfer(msg.value); + + emit IGateway.OutboundMessageAccepted(dest, channel.outboundNonce, payload); + } + + /// @dev Outbound message can be disabled globally or on a per-channel basis. + function _ensureOutboundMessagingEnabled(Channel storage ch) internal view { + CoreStorage.Layout storage $ = CoreStorage.layout(); + if ($.mode != OperatingMode.Normal || ch.mode != OperatingMode.Normal) { + revert Disabled(); + } + } + + /// @dev Ensure that the specified parachain has a channel allocated + function _ensureChannel(ParaID paraID) internal view returns (Channel storage ch) { + ch = CoreStorage.layout().channels[paraID]; + // A channel always has an agent specified. + if (ch.agent == address(0)) { + revert ChannelDoesNotExist(); + } + } + + /// @dev Invoke some code within an agent + function _invokeOnAgent(address agent, bytes memory data) internal returns (bytes memory) { + (bool success, bytes memory returndata) = (Agent(payable(agent)).invoke(AGENT_EXECUTOR, data)); + return Call.verifyResult(success, returndata); + } + + /// @dev Transfer ether from an agent + function _transferNativeFromAgent(address agent, address payable recipient, uint256 amount) internal { + bytes memory call = abi.encodeCall(AgentExecutor.transferNative, (recipient, amount)); + _invokeOnAgent(agent, call); + } + + /** + * Upgrades + */ + + /// @dev Initialize storage in the gateway + /// NOTE: This is not externally accessible as this function selector is overshadowed in the proxy + function initialize(bytes memory data) external { + // Prevent initialization of storage in implementation contract + if (ERC1967.load() == address(0)) { + revert Unauthorized(); + } + + (uint256 defaultFee, uint256 defaultReward, uint256 registerTokenFee, uint256 sendTokenFee) = + abi.decode(data, (uint256, uint256, uint256, uint256)); + + CoreStorage.Layout storage $ = CoreStorage.layout(); + + $.mode = OperatingMode.Normal; + $.defaultFee = defaultFee; + $.defaultReward = defaultReward; + + // Initialize an agent & channel for BridgeHub + address bridgeHubAgent = address(new Agent(BRIDGE_HUB_AGENT_ID)); + $.agents[BRIDGE_HUB_AGENT_ID] = bridgeHubAgent; + $.channels[BRIDGE_HUB_PARA_ID] = Channel({ + mode: OperatingMode.Normal, + agent: bridgeHubAgent, + inboundNonce: 0, + outboundNonce: 0, + fee: defaultFee, + reward: defaultReward + }); + + // Initialize an agent & channel for AssetHub + address assetHubAgent = address(new Agent(ASSET_HUB_AGENT_ID)); + $.agents[ASSET_HUB_AGENT_ID] = assetHubAgent; + $.channels[ASSET_HUB_PARA_ID] = Channel({ + mode: OperatingMode.Normal, + agent: assetHubAgent, + inboundNonce: 0, + outboundNonce: 0, + fee: defaultFee, + reward: defaultReward + }); + + Assets.initialize(registerTokenFee, sendTokenFee); + } +} diff --git a/contracts/src/GatewayProxy.sol b/contracts/src/GatewayProxy.sol new file mode 100644 index 0000000000000..ff81879c01c59 --- /dev/null +++ b/contracts/src/GatewayProxy.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {ERC1967} from "./utils/ERC1967.sol"; +import {IInitializable} from "./interfaces/IInitializable.sol"; + +contract GatewayProxy is IInitializable { + error Unauthorized(); + error NativeCurrencyNotAccepted(); + + constructor(address implementation, bytes memory params) { + // Store the address of the implementation contract + ERC1967.store(implementation); + // Initialize storage by calling the implementation's `initialize(bytes)` function + // using `delegatecall`. + (bool success,) = implementation.delegatecall(abi.encodeCall(IInitializable.initialize, params)); + if (!success) { + revert InitializationFailed(); + } + } + + // Prevent fallback() from calling `initialize(bytes)` on the implementation contract + function initialize(bytes calldata) external pure { + revert Unauthorized(); + } + + fallback() external payable { + address implementation = ERC1967.load(); + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } + + // Prevent users from unwittingly sending ether to the gateway, as these funds + // would otherwise be lost forever. + receive() external payable { + revert NativeCurrencyNotAccepted(); + } +} diff --git a/contracts/src/SubstrateTypes.sol b/contracts/src/SubstrateTypes.sol new file mode 100644 index 0000000000000..d500610251da2 --- /dev/null +++ b/contracts/src/SubstrateTypes.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {ScaleCodec} from "./utils/ScaleCodec.sol"; +import {ParaID} from "./Types.sol"; + +/** + * @title SCALE encoders for common Substrate types + */ +library SubstrateTypes { + error UnsupportedCompactEncoding(); + + /** + * @dev Encodes `MultiAddress::Id`: https://crates.parity.io/sp_runtime/enum.MultiAddress.html#variant.Id + * @return bytes SCALE-encoded bytes + */ + // solhint-disable-next-line func-name-mixedcase + function MultiAddressWithID(bytes32 account) internal pure returns (bytes memory) { + return bytes.concat(hex"00", account); + } + + /** + * @dev Encodes `H160`: https://crates.parity.io/sp_core/struct.H160.html + * @return bytes SCALE-encoded bytes + */ + // solhint-disable-next-line func-name-mixedcase + function H160(address account) internal pure returns (bytes memory) { + return abi.encodePacked(account); + } + + function VecU8(bytes memory input) internal pure returns (bytes memory) { + return bytes.concat(ScaleCodec.checkedEncodeCompactU32(input.length), input); + } + + /** + * @dev Encodes `Option::None`: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None + * @return bytes SCALE-encoded bytes + */ + // solhint-disable-next-line func-name-mixedcase + function None() internal pure returns (bytes memory) { + return hex"00"; + } + + // solhint-disable-next-line func-name-mixedcase + function OptionParaID(ParaID v) internal pure returns (bytes memory) { + if (ParaID.unwrap(v) == 0) { + return hex"00"; + } else { + return bytes.concat(bytes1(0x01), ScaleCodec.encodeU32(uint32(ParaID.unwrap(v)))); + } + } + + /** + * @dev SCALE-encodes `router_primitives::inbound::VersionedMessage` containing payload + * `NativeTokensMessage::Create` + */ + // solhint-disable-next-line func-name-mixedcase + function RegisterToken(address gateway, address token, bytes2 createCallIndex) + internal + view + returns (bytes memory) + { + return bytes.concat( + bytes1(0x00), + ScaleCodec.encodeU64(uint64(block.chainid)), + bytes1(0x00), + SubstrateTypes.H160(gateway), + SubstrateTypes.H160(token), + createCallIndex + ); + } + + /** + * @dev SCALE-encodes `router_primitives::inbound::VersionedMessage` containing payload + * `NativeTokensMessage::Mint` + */ + // solhint-disable-next-line func-name-mixedcase + function SendToken(address gateway, address token, bytes32 recipient, uint128 amount) + internal + view + returns (bytes memory) + { + return bytes.concat( + bytes1(0x00), + ScaleCodec.encodeU64(uint64(block.chainid)), + bytes1(0x01), + SubstrateTypes.H160(gateway), + SubstrateTypes.H160(token), + bytes1(0x00), + recipient, + ScaleCodec.encodeU128(amount) + ); + } + + function SendToken(address gateway, address token, ParaID paraID, bytes32 recipient, uint128 amount) + internal + view + returns (bytes memory) + { + return bytes.concat( + bytes1(0x00), + ScaleCodec.encodeU64(uint64(block.chainid)), + bytes1(0x01), + SubstrateTypes.H160(gateway), + SubstrateTypes.H160(token), + bytes1(0x01), + ScaleCodec.encodeU32(uint32(ParaID.unwrap(paraID))), + recipient, + ScaleCodec.encodeU128(amount) + ); + } + + function SendToken(address gateway, address token, ParaID paraID, address recipient, uint128 amount) + internal + view + returns (bytes memory) + { + return bytes.concat( + bytes1(0x00), + ScaleCodec.encodeU64(uint64(block.chainid)), + bytes1(0x01), + SubstrateTypes.H160(gateway), + SubstrateTypes.H160(token), + bytes1(0x02), + ScaleCodec.encodeU32(uint32(ParaID.unwrap(paraID))), + abi.encodePacked(recipient), + ScaleCodec.encodeU128(amount) + ); + } +} diff --git a/contracts/src/Types.sol b/contracts/src/Types.sol new file mode 100644 index 0000000000000..432f6782f35b7 --- /dev/null +++ b/contracts/src/Types.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +type ParaID is uint256; + +using {ParaIDEq as ==, ParaIDNe as !=} for ParaID global; + +function ParaIDEq(ParaID a, ParaID b) pure returns (bool) { + return ParaID.unwrap(a) == ParaID.unwrap(b); +} + +function ParaIDNe(ParaID a, ParaID b) pure returns (bool) { + return !ParaIDEq(a, b); +} + +/// @dev A messaging channel for a Polkadot parachain +struct Channel { + /// @dev The operating mode for this channel. Can be used to + /// disable messaging on a per-channel basis. + OperatingMode mode; + /// @dev The current nonce for the inbound lane + uint64 inboundNonce; + /// @dev The current node for the outbound lane + uint64 outboundNonce; + /// @dev The address of the agent of the parachain owning this channel + address agent; + /// @dev The fee charged to users for submitting outbound messages + uint256 fee; + /// @dev The reward disbursed to message relayers for submitting inbound messages + uint256 reward; +} + +/// @dev Inbound message from a Polkadot parachain (via BridgeHub) +struct InboundMessage { + /// @dev The parachain from which this message originated + ParaID origin; + /// @dev The channel nonce + uint64 nonce; + /// @dev The command to execute + Command command; + /// @dev The Parameters for the command + bytes params; +} + +enum OperatingMode { + Normal, + RejectingOutboundMessages +} + +// Initial configuration for bridge +struct Config { + /// @dev The default fee charged to users for submitting outbound messages. + uint256 fee; + /// @dev The default reward disbursed to message relayers for submitting inbound messages. + uint256 reward; + /// @dev The extra fee charged for registering tokens. + uint256 registerNativeTokenFee; + /// @dev The extra fee charged for sending tokens. + uint256 sendNativeTokenFee; +} + +/// @dev Messages from Polkadot take the form of these commands. +enum Command { + AgentExecute, + Upgrade, + CreateAgent, + CreateChannel, + UpdateChannel, + SetOperatingMode, + TransferNativeFromAgent +} + +enum AgentExecuteCommand {TransferToken} diff --git a/contracts/src/Verification.sol b/contracts/src/Verification.sol new file mode 100644 index 0000000000000..c247a18b38b8f --- /dev/null +++ b/contracts/src/Verification.sol @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {SubstrateMerkleProof} from "./utils/SubstrateMerkleProof.sol"; +import {BeefyClient} from "./BeefyClient.sol"; +import {ScaleCodec} from "./utils/ScaleCodec.sol"; +import {SubstrateTypes} from "./SubstrateTypes.sol"; + +library Verification { + /// @dev Merkle proof for parachain header finalized by BEEFY + /// Reference: https://github.com/paritytech/polkadot/blob/09b61286da11921a3dda0a8e4015ceb9ef9cffca/runtime/rococo/src/lib.rs#L1312 + struct HeadProof { + /// @dev The leaf index of the parachain being proven + uint256 pos; + /// @dev The number of leaves in the merkle tree + uint256 width; + /// @dev The proof items + bytes32[] proof; + } + + /// @dev An MMRLeaf without the `leaf_extra` field. + /// Reference: https://github.com/paritytech/substrate/blob/14e0a0b628f9154c5a2c870062c3aac7df8983ed/primitives/consensus/beefy/src/mmr.rs#L52 + struct MMRLeafPartial { + uint8 version; + uint32 parentNumber; + bytes32 parentHash; + uint64 nextAuthoritySetID; + uint32 nextAuthoritySetLen; + bytes32 nextAuthoritySetRoot; + } + + /// @dev Parachain header + /// References: + /// * https://paritytech.github.io/substrate/master/sp_runtime/generic/struct.Header.html + /// * https://github.com/paritytech/substrate/blob/14e0a0b628f9154c5a2c870062c3aac7df8983ed/primitives/runtime/src/generic/header.rs#L41 + struct ParachainHeader { + bytes32 parentHash; + uint256 number; + bytes32 stateRoot; + bytes32 extrinsicsRoot; + DigestItem[] digestItems; + } + + /// @dev Represents a digest item within a parachain header. + /// References: + /// * https://paritytech.github.io/substrate/master/sp_runtime/generic/enum.DigestItem.html + /// * https://github.com/paritytech/substrate/blob/14e0a0b628f9154c5a2c870062c3aac7df8983ed/primitives/runtime/src/generic/digest.rs#L75 + struct DigestItem { + uint256 kind; + bytes4 consensusEngineID; + bytes data; + } + + /// @dev A chain of proofs + struct Proof { + /// @dev The parachain header containing the message commitment as a digest item + ParachainHeader header; + /// @dev The proof used to generate a merkle root of parachain heads + HeadProof headProof; + /// @dev The MMR leaf to be proven + MMRLeafPartial leafPartial; + /// @dev The MMR leaf prove + bytes32[] leafProof; + /// @dev The order in which proof items should be combined + uint256 leafProofOrder; + } + + error InvalidParachainHeader(); + + /// @dev IDs of enum variants of DigestItem + /// Reference: https://github.com/paritytech/substrate/blob/14e0a0b628f9154c5a2c870062c3aac7df8983ed/primitives/runtime/src/generic/digest.rs#L201 + uint256 public constant DIGEST_ITEM_OTHER = 0; + uint256 public constant DIGEST_ITEM_CONSENSUS = 4; + uint256 public constant DIGEST_ITEM_SEAL = 5; + uint256 public constant DIGEST_ITEM_PRERUNTIME = 6; + uint256 public constant DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED = 8; + + /// @dev Verify the message commitment by applying several proofs + /// + /// 1. First check that the commitment is included in the digest items of the parachain header + /// 2. Generate the root of the parachain heads merkle tree + /// 3. Construct an MMR leaf containing the parachain heads root. + /// 4. Verify that the MMR leaf is included in the MMR maintained by the BEEFY light client. + /// + /// Background info: + /// + /// In the Polkadot relay chain, for every block: + /// 1. A merkle root of finalized parachain headers is constructed: + /// https://github.com/paritytech/polkadot/blob/09b61286da11921a3dda0a8e4015ceb9ef9cffca/runtime/rococo/src/lib.rs#L1312. + /// 2. An MMR leaf is produced, containing this parachain headers root, and is then inserted into the + /// MMR maintained by the `merkle-mountain-range` pallet: + /// https://github.com/paritytech/substrate/tree/master/frame/merkle-mountain-range + /// + /// @param beefyClient The address of the BEEFY light client + /// @param encodedParaID The SCALE-encoded parachain ID of BridgeHub + /// @param commitment The message commitment root expected to be contained within the + /// digest of BridgeHub parachain header. + /// @param proof The chain of proofs described above + function verifyCommitment(address beefyClient, bytes4 encodedParaID, bytes32 commitment, Proof calldata proof) + external + view + returns (bool) + { + // Verify that parachain header contains the commitment + if (!isCommitmentInHeaderDigest(commitment, proof.header)) { + return false; + } + + // Compute the merkle leaf hash of our parachain + bytes32 parachainHeadHash = createParachainHeaderMerkleLeaf(encodedParaID, proof.header); + + if (proof.headProof.pos >= proof.headProof.width) { + return false; + } + + // Compute the merkle root hash of all parachain heads + bytes32 parachainHeadsRoot = SubstrateMerkleProof.computeRoot( + parachainHeadHash, proof.headProof.pos, proof.headProof.width, proof.headProof.proof + ); + + bytes32 leafHash = createMMRLeaf(proof.leafPartial, parachainHeadsRoot); + + // Verify that the MMR leaf is part of the MMR maintained by the BEEFY light client + return BeefyClient(beefyClient).verifyMMRLeafProof(leafHash, proof.leafProof, proof.leafProofOrder); + } + + // Verify that a message commitment is in the header digest + function isCommitmentInHeaderDigest(bytes32 commitment, ParachainHeader calldata header) + internal + pure + returns (bool) + { + for (uint256 i = 0; i < header.digestItems.length; i++) { + DigestItem memory item = header.digestItems[i]; + if (item.kind == DIGEST_ITEM_OTHER && item.data.length == 32 && commitment == bytes32(item.data)) { + return true; + } + } + return false; + } + + // SCALE-Encodes: Vec + // Reference: https://github.com/paritytech/substrate/blob/14e0a0b628f9154c5a2c870062c3aac7df8983ed/primitives/runtime/src/generic/digest.rs#L40 + function encodeDigestItems(DigestItem[] calldata digestItems) internal pure returns (bytes memory) { + // encode all digest items into a buffer + bytes memory accum = hex""; + for (uint256 i = 0; i < digestItems.length; i++) { + accum = bytes.concat(accum, encodeDigestItem(digestItems[i])); + } + // Encode number of digest items, followed by encoded digest items + return bytes.concat(ScaleCodec.checkedEncodeCompactU32(uint32(digestItems.length)), accum); + } + + function encodeDigestItem(DigestItem calldata digestItem) internal pure returns (bytes memory) { + if (digestItem.kind == DIGEST_ITEM_PRERUNTIME) { + return bytes.concat( + bytes1(uint8(DIGEST_ITEM_PRERUNTIME)), + digestItem.consensusEngineID, + ScaleCodec.checkedEncodeCompactU32(digestItem.data.length), + digestItem.data + ); + } else if (digestItem.kind == DIGEST_ITEM_CONSENSUS) { + return bytes.concat( + bytes1(uint8(DIGEST_ITEM_CONSENSUS)), + digestItem.consensusEngineID, + ScaleCodec.checkedEncodeCompactU32(digestItem.data.length), + digestItem.data + ); + } else if (digestItem.kind == DIGEST_ITEM_SEAL) { + return bytes.concat( + bytes1(uint8(DIGEST_ITEM_SEAL)), + digestItem.consensusEngineID, + ScaleCodec.checkedEncodeCompactU32(digestItem.data.length), + digestItem.data + ); + } else if (digestItem.kind == DIGEST_ITEM_OTHER) { + return bytes.concat( + bytes1(uint8(DIGEST_ITEM_OTHER)), + ScaleCodec.checkedEncodeCompactU32(digestItem.data.length), + digestItem.data + ); + } else if (digestItem.kind == DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED) { + return bytes.concat(bytes1(uint8(DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED))); + } else { + revert InvalidParachainHeader(); + } + } + + // Creates a keccak hash of a SCALE-encoded parachain header + function createParachainHeaderMerkleLeaf(bytes4 encodedParaID, ParachainHeader calldata header) + internal + pure + returns (bytes32) + { + // Encode Parachain header + bytes memory encodedHeader = bytes.concat( + // H256 + header.parentHash, + // Compact unsigned int + ScaleCodec.checkedEncodeCompactU32(uint32(header.number)), + // H256 + header.stateRoot, + // H256 + header.extrinsicsRoot, + // Vec + encodeDigestItems(header.digestItems) + ); + + // Hash of encoded parachain header merkle leaf + return keccak256( + bytes.concat( + // u32 + encodedParaID, + // Vec + ScaleCodec.checkedEncodeCompactU32(encodedHeader.length), + encodedHeader + ) + ); + } + + function createParachainHeader(bytes4 encodedParaID, ParachainHeader calldata header) + internal + pure + returns (bytes memory) + { + bytes memory encodedHeader = bytes.concat( + // H256 + header.parentHash, + // Compact unsigned int + ScaleCodec.checkedEncodeCompactU32(header.number), + // H256 + header.stateRoot, + // H256 + header.extrinsicsRoot, + // Vec + ScaleCodec.checkedEncodeCompactU32(header.digestItems.length), + encodeDigestItems(header.digestItems) + ); + + return bytes.concat( + // u32 + encodedParaID, + // length of encoded header + ScaleCodec.checkedEncodeCompactU32(uint32(encodedHeader.length)), + encodedHeader + ); + } + + // SCALE-encode: MMRLeaf + // Reference: https://github.com/paritytech/substrate/blob/14e0a0b628f9154c5a2c870062c3aac7df8983ed/primitives/consensus/beefy/src/mmr.rs#L52 + function createMMRLeaf(MMRLeafPartial memory leaf, bytes32 parachainHeadsRoot) internal pure returns (bytes32) { + bytes memory encodedLeaf = bytes.concat( + ScaleCodec.encodeU8(leaf.version), + ScaleCodec.encodeU32(leaf.parentNumber), + leaf.parentHash, + ScaleCodec.encodeU64(leaf.nextAuthoritySetID), + ScaleCodec.encodeU32(leaf.nextAuthoritySetLen), + leaf.nextAuthoritySetRoot, + parachainHeadsRoot + ); + return keccak256(encodedLeaf); + } +} diff --git a/contracts/src/interfaces/IERC20.sol b/contracts/src/interfaces/IERC20.sol new file mode 100644 index 0000000000000..58b4f3a8aa147 --- /dev/null +++ b/contracts/src/interfaces/IERC20.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 Axelar Network + +pragma solidity ^0.8.20; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + error InvalidAccount(); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} diff --git a/contracts/src/interfaces/IGateway.sol b/contracts/src/interfaces/IGateway.sol new file mode 100644 index 0000000000000..ecafa268f342b --- /dev/null +++ b/contracts/src/interfaces/IGateway.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {OperatingMode, InboundMessage, ParaID} from "../Types.sol"; +import {Verification} from "../Verification.sol"; + +interface IGateway { + /** + * Events + */ + + // Emitted when inbound message has been dispatched + event InboundMessageDispatched(ParaID indexed origin, uint64 nonce, bool success); + + // Emitted when an outbound message has been accepted for delivery to a Polkadot parachain + event OutboundMessageAccepted(ParaID indexed destination, uint64 nonce, bytes payload); + + // Emitted when an agent has been created for a consensus system on Polkadot + event AgentCreated(bytes32 agentID, address agent); + + // Emitted when a channel has been created + event ChannelCreated(ParaID indexed paraID); + + // Emitted when a channel has been updated + event ChannelUpdated(ParaID indexed paraID); + + // Emitted when the gateway is upgraded + event Upgraded(address indexed implementation); + + // Emitted when the operating mode is changed + event OperatingModeChanged(OperatingMode mode); + + // Emitted when funds are withdrawn from an agent + event AgentFundsWithdrawn(bytes32 indexed agentID, address indexed recipient, uint256 amount); + + event TokenRegistered(address token); + + event TokenSent(address token, ParaID destinationChain, bytes destinationAddress, uint128 amount); + + /** + * Getters + */ + + function operatingMode() external view returns (OperatingMode); + function channelOperatingModeOf(ParaID paraID) external view returns (OperatingMode); + function channelFeeRewardOf(ParaID paraID) external view returns (uint256, uint256); + function channelNoncesOf(ParaID paraID) external view returns (uint64, uint64); + function agentOf(bytes32 agentID) external view returns (address); + function implementation() external view returns (address); + + /** + * Messaging + */ + + // Submit an inbound message from Polkadot + function submitInbound( + InboundMessage calldata message, + bytes32[] calldata leafProof, + Verification.Proof calldata headerProof + ) external; + + /** + * Token Transfers + */ + + /// @dev Send a message to the AssetHub parachain to register a new fungible asset + /// in the `ForeignAssets` pallet. + function registerToken(address token) external payable; + + /// @dev Send ERC20 tokens to parachain `destinationChain` and deposit into account `destinationAddress` + function sendToken(address token, ParaID destinationChain, bytes32 destinationAddress, uint128 amount) + external + payable; + + /// @dev Send ERC20 tokens to parachain `destinationChain` and deposit into account `destinationAddress` + function sendToken(address token, ParaID destinationChain, address destinationAddress, uint128 amount) + external + payable; +} diff --git a/contracts/src/interfaces/IInitializable.sol b/contracts/src/interfaces/IInitializable.sol new file mode 100644 index 0000000000000..e191a8a55f434 --- /dev/null +++ b/contracts/src/interfaces/IInitializable.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +/** + * @title Initialization of gateway contracts + */ +interface IInitializable { + error InitializationFailed(); + + function initialize(bytes calldata data) external; +} diff --git a/contracts/src/storage/AssetsStorage.sol b/contracts/src/storage/AssetsStorage.sol new file mode 100644 index 0000000000000..7297a25eadc63 --- /dev/null +++ b/contracts/src/storage/AssetsStorage.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {Agent} from "../Agent.sol"; +import {ParaID} from "../Types.sol"; + +library AssetsStorage { + struct Layout { + uint256 registerTokenFee; + uint256 sendTokenFee; + } + + bytes32 internal constant SLOT = keccak256("org.snowbridge.storage.assets"); + + function layout() internal pure returns (Layout storage $) { + bytes32 slot = SLOT; + assembly { + $.slot := slot + } + } +} diff --git a/contracts/src/storage/CoreStorage.sol b/contracts/src/storage/CoreStorage.sol new file mode 100644 index 0000000000000..4053281818aeb --- /dev/null +++ b/contracts/src/storage/CoreStorage.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +import {AgentExecutor} from "../AgentExecutor.sol"; +import {Agent} from "../Agent.sol"; +import {Channel, OperatingMode, ParaID} from "../Types.sol"; + +library CoreStorage { + struct Layout { + // Operating mode: + OperatingMode mode; + // Message channels + mapping(ParaID paraID => Channel) channels; + // Agents + mapping(bytes32 agentID => address) agents; + // The default fee charged to users for submitting outbound message to Polkadot + uint256 defaultFee; + // The default reward given to relayers for submitting inbound messages from Polkadot + uint256 defaultReward; + } + + bytes32 internal constant SLOT = keccak256("org.snowbridge.storage.core"); + + function layout() internal pure returns (Layout storage $) { + bytes32 slot = SLOT; + assembly { + $.slot := slot + } + } +} diff --git a/contracts/src/utils/Address.sol b/contracts/src/utils/Address.sol new file mode 100644 index 0000000000000..acddf38d7354f --- /dev/null +++ b/contracts/src/utils/Address.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 Axelar Network +// SPDX-FileCopyrightText: 2023 Snowfork + +pragma solidity ^0.8.20; + +library Address { + // Checks whether `account` is a contract + function isContract(address account) internal view returns (bool) { + // https://eips.ethereum.org/EIPS/eip-1052 + // keccak256('') == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 + return account.codehash != bytes32(0) + && account.codehash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + } +} diff --git a/core/packages/contracts/src/utils/Bitfield.sol b/contracts/src/utils/Bitfield.sol similarity index 99% rename from core/packages/contracts/src/utils/Bitfield.sol rename to contracts/src/utils/Bitfield.sol index fdfc159a1a353..63be99218f042 100644 --- a/core/packages/contracts/src/utils/Bitfield.sol +++ b/contracts/src/utils/Bitfield.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.20; -import "./Bits.sol"; +import {Bits} from "./Bits.sol"; library Bitfield { using Bits for uint256; diff --git a/core/packages/contracts/src/utils/Bits.sol b/contracts/src/utils/Bits.sol similarity index 100% rename from core/packages/contracts/src/utils/Bits.sol rename to contracts/src/utils/Bits.sol diff --git a/contracts/src/utils/Call.sol b/contracts/src/utils/Call.sol new file mode 100644 index 0000000000000..02e80c5674a04 --- /dev/null +++ b/contracts/src/utils/Call.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 OpenZeppelin +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +// Derived from OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) +library Call { + function verifyResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + /// @solidity memory-safe-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(); + } + } + } +} diff --git a/contracts/src/utils/ERC1967.sol b/contracts/src/utils/ERC1967.sol new file mode 100644 index 0000000000000..1cba006be0317 --- /dev/null +++ b/contracts/src/utils/ERC1967.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.20; + +/// @title Minimal implementation of ERC1967 storage slot +library ERC1967 { + // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) + bytes32 public constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + function load() internal view returns (address implementation) { + assembly { + implementation := sload(_IMPLEMENTATION_SLOT) + } + } + + function store(address implementation) internal { + assembly { + sstore(_IMPLEMENTATION_SLOT, implementation) + } + } +} diff --git a/core/packages/contracts/src/utils/MMRProof.sol b/contracts/src/utils/MMRProof.sol similarity index 80% rename from core/packages/contracts/src/utils/MMRProof.sol rename to contracts/src/utils/MMRProof.sol index 6d5d7a2b306a6..a560c78413216 100644 --- a/core/packages/contracts/src/utils/MMRProof.sol +++ b/contracts/src/utils/MMRProof.sol @@ -3,6 +3,10 @@ pragma solidity 0.8.20; library MMRProof { + error ProofSizeExceeded(); + + uint256 internal constant MAXIMUM_PROOF_SIZE = 256; + /** * @dev Verify inclusion of a leaf in an MMR * @param root MMR root hash @@ -15,6 +19,11 @@ library MMRProof { pure returns (bool) { + // Size of the proof is bounded, since `proofOrder` can only contain `MAXIMUM_PROOF_SIZE` orderings. + if (proof.length > MAXIMUM_PROOF_SIZE) { + revert ProofSizeExceeded(); + } + bytes32 acc = leafHash; for (uint256 i = 0; i < proof.length;) { acc = hashPairs(acc, proof[i], (proofOrder >> i) & 1); diff --git a/contracts/src/utils/SafeTransfer.sol b/contracts/src/utils/SafeTransfer.sol new file mode 100644 index 0000000000000..4cec84caf9375 --- /dev/null +++ b/contracts/src/utils/SafeTransfer.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 Axelar Network +// SPDX-FileCopyrightText: 2023 Snowfork + +pragma solidity ^0.8.20; + +import {IERC20} from "../interfaces/IERC20.sol"; + +error TokenTransferFailed(); +error NativeTransferFailed(); + +library SafeTokenCall { + function safeCall(IERC20 token, bytes memory callData) internal { + (bool success, bytes memory returnData) = address(token).call(callData); + bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); + if (!transferred || address(token).code.length == 0) { + revert TokenTransferFailed(); + } + } +} + +library SafeTokenTransfer { + function safeTransfer(IERC20 token, address receiver, uint256 amount) internal { + SafeTokenCall.safeCall(token, abi.encodeCall(IERC20.transfer, (receiver, amount))); + } +} + +library SafeTokenTransferFrom { + function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal { + SafeTokenCall.safeCall(token, abi.encodeCall(IERC20.transferFrom, (from, to, amount))); + } +} + +library SafeNativeTransfer { + function safeNativeTransfer(address payable receiver, uint256 amount) internal { + bool success; + assembly { + success := call(gas(), receiver, amount, 0, 0, 0, 0) + } + if (!success) { + revert NativeTransferFailed(); + } + } +} diff --git a/core/packages/contracts/src/ScaleCodec.sol b/contracts/src/utils/ScaleCodec.sol similarity index 78% rename from core/packages/contracts/src/ScaleCodec.sol rename to contracts/src/utils/ScaleCodec.sol index ca75537b045cc..57a4388e482ae 100644 --- a/core/packages/contracts/src/ScaleCodec.sol +++ b/contracts/src/utils/ScaleCodec.sol @@ -2,9 +2,11 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.20; -import "./utils/Bytes.sol"; - library ScaleCodec { + error UnsupportedCompactEncoding(); + + uint256 internal constant MAX_COMPACT_ENCODABLE_UINT = 2 ** 30 - 1; + // Sources: // * https://ethereum.stackexchange.com/questions/15350/how-to-convert-an-bytes-to-address-in-solidity/50528 // * https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel @@ -102,7 +104,8 @@ library ScaleCodec { return bytes1(input); } - function encodeCompactUint(uint256 value) internal pure returns (bytes memory) { + // Supports compact encoding of integers in [0, uint32.MAX] + function encodeCompactU32(uint32 value) internal pure returns (bytes memory) { if (value <= 2 ** 6 - 1) { // add single byte flag return abi.encodePacked(uint8(value << 2)); @@ -113,29 +116,14 @@ library ScaleCodec { // add four byte flag and create little endian encoding return abi.encodePacked(ScaleCodec.reverse32(uint32((value << 2)) + 2)); } else { - if (value <= 2 ** 62 - 1) { - uint8 numBytes = getLengthBytes(value); - uint8 prefix = ((numBytes - 4) << 2) + 3; - bytes memory paddedWithZeros = abi.encodePacked(ScaleCodec.reverse64(uint64((value << 8)) + prefix)); - bytes memory encodedValue = Bytes.removeEndingZero(paddedWithZeros); - return encodedValue; - } else { - uint8 numBytes = getLengthBytes(value); - uint8 prefix = ((numBytes - 4) << 2) + 3; - bytes memory paddedWithZeros = abi.encodePacked(ScaleCodec.reverse128(uint128((value << 8)) + prefix)); - bytes memory encodedValue = Bytes.removeEndingZero(paddedWithZeros); - return encodedValue; - } + return abi.encodePacked(uint8(3), ScaleCodec.reverse32(value)); } } - function getLengthBytes(uint256 value) internal pure returns (uint8) { - uint8 length = 0; - uint256 temp = value; - while (temp != 0) { - temp >>= 8; - length++; + function checkedEncodeCompactU32(uint256 value) internal pure returns (bytes memory) { + if (value > type(uint32).max) { + revert UnsupportedCompactEncoding(); } - return length; + return encodeCompactU32(uint32(value)); } } diff --git a/core/packages/contracts/src/utils/MerkleProof.sol b/contracts/src/utils/SubstrateMerkleProof.sol similarity index 90% rename from core/packages/contracts/src/utils/MerkleProof.sol rename to contracts/src/utils/SubstrateMerkleProof.sol index 60cfaa4391704..7626fe111216e 100644 --- a/core/packages/contracts/src/utils/MerkleProof.sol +++ b/contracts/src/utils/SubstrateMerkleProof.sol @@ -2,7 +2,8 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.20; -library MerkleProof { +// Used to verify merkle proofs generated by https://github.com/paritytech/substrate/tree/master/utils/binary-merkle-tree +library SubstrateMerkleProof { /** * @notice Verify that a specific leaf element is part of the Merkle Tree at a specific position in the tree * @@ -19,7 +20,7 @@ library MerkleProof { * @param proof the array of proofs to help verify the leaf's membership, ordered from leaf to root * @return a boolean value representing the success or failure of the operation */ - function verify(bytes32 root, bytes32 leaf, uint256 position, uint256 width, bytes32[] memory proof) + function verify(bytes32 root, bytes32 leaf, uint256 position, uint256 width, bytes32[] calldata proof) internal pure returns (bool) @@ -30,7 +31,7 @@ library MerkleProof { return root == computeRoot(leaf, position, width, proof); } - function computeRoot(bytes32 leaf, uint256 position, uint256 width, bytes32[] memory proof) + function computeRoot(bytes32 leaf, uint256 position, uint256 width, bytes32[] calldata proof) internal pure returns (bytes32) diff --git a/contracts/test/Agent.t.sol b/contracts/test/Agent.t.sol new file mode 100644 index 0000000000000..44bc55aacd5f7 --- /dev/null +++ b/contracts/test/Agent.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {Agent} from "../src/Agent.sol"; + +contract Executor { + error Failure(); + + function foo() external pure returns (bool) { + return true; + } + + function fail() external pure { + revert Failure(); + } +} + +contract AgentTest is Test { + bytes32 public constant AGENT_ID = keccak256("1000"); + Agent public agent; + address public executor; + + function setUp() public { + agent = new Agent(AGENT_ID); + executor = address(new Executor()); + } + + function testInvoke() public { + (bool success, bytes memory result) = agent.invoke(executor, abi.encodeCall(Executor.foo, ())); + assertEq(success, true); + assertEq(result, abi.encode(true)); + } + + function testInvokeUnauthorized() public { + address user = makeAddr("user"); + + vm.expectRevert(Agent.Unauthorized.selector); + + hoax(user); + agent.invoke(executor, abi.encodeCall(Executor.foo, ())); + } + + function testInvokeFail() public { + (bool success, bytes memory result) = agent.invoke(executor, abi.encodeCall(Executor.fail, ())); + assertEq(success, false); + assertEq(result, bytes.concat(Executor.Failure.selector)); + } +} diff --git a/core/packages/contracts/test/BeefyClient.t.sol b/contracts/test/BeefyClient.t.sol similarity index 65% rename from core/packages/contracts/test/BeefyClient.t.sol rename to contracts/test/BeefyClient.t.sol index bf214d7e63ae5..8a24f7e1cbe5f 100644 --- a/core/packages/contracts/test/BeefyClient.t.sol +++ b/contracts/test/BeefyClient.t.sol @@ -1,20 +1,24 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; -import "openzeppelin/utils/Strings.sol"; -import "forge-std/Test.sol"; -import "forge-std/console.sol"; +import {Strings} from "openzeppelin/utils/Strings.sol"; +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; +import {stdJson} from "forge-std/StdJson.sol"; -import "./mocks/BeefyClientMock.sol"; -import "../src/ScaleCodec.sol"; -import "../src/utils/Bitfield.sol"; +import {BeefyClient} from "../src/BeefyClient.sol"; +import {BeefyClientMock} from "./mocks/BeefyClientMock.sol"; +import {ScaleCodec} from "../src/utils/ScaleCodec.sol"; +import {Bitfield} from "../src/utils/Bitfield.sol"; contract BeefyClientTest is Test { + using stdJson for string; + BeefyClientMock beefyClient; uint8 randaoCommitDelay; uint8 randaoCommitExpiration; uint32 blockNumber; - uint32 difficulty; + uint32 prevRandao; uint32 setSize; uint32 setId; uint128 currentSetId; @@ -33,45 +37,52 @@ contract BeefyClientTest is Test { BeefyClient.MMRLeaf mmrLeaf; uint256 leafProofOrder; bytes2 mmrRootID = bytes2("mh"); + string beefyCommitmentFile; + string beefyCommitmentRaw; + string beefyValidatorSetFile; + string beefyValidatorSetRaw; + string beefyValidatorProofFile; + string beefyValidatorProofRaw; + string beefyFinalBitFieldFile; function setUp() public { - randaoCommitDelay = 3; - randaoCommitExpiration = 8; - difficulty = 377; + randaoCommitDelay = uint8(vm.envOr("RANDAO_COMMIT_DELAY", uint256(3))); + randaoCommitExpiration = uint8(vm.envOr("RANDAO_COMMIT_EXP", uint256(8))); + prevRandao = uint32(vm.envOr("PREV_RANDAO", uint256(377))); beefyClient = new BeefyClientMock(randaoCommitDelay, randaoCommitExpiration); - // Allocate for input variables - string[] memory inputs = new string[](10); - inputs[0] = "node_modules/.bin/ts-node"; - inputs[1] = "scripts/ffiWrapper.ts"; - inputs[2] = "GenerateInitialSet"; + beefyCommitmentFile = string.concat(vm.projectRoot(), "/test/data/beefy-commitment.json"); + beefyCommitmentRaw = vm.readFile(beefyCommitmentFile); - // generate initial fixture data with ffi - (blockNumber, setId, setSize, bitSetArray, absentBitSetArray, commitHash, mmrRoot) = - abi.decode(vm.ffi(inputs), (uint32, uint32, uint32, uint256[], uint256[], bytes32, bytes32)); - bitfield = beefyClient.createInitialBitfield(bitSetArray, setSize); - absentBitfield = beefyClient.createInitialBitfield(absentBitSetArray, setSize); + beefyValidatorSetFile = string.concat(vm.projectRoot(), "/test/data/beefy-validator-set.json"); + beefyValidatorSetRaw = vm.readFile(beefyValidatorSetFile); - // To avoid another round of ffi in multiple tests - // except for the initial merkle root and proof for validators - // we also precalculate finalValidatorProofs and cached here - finalBitfield = - Bitfield.subsample(difficulty, bitfield, beefyClient.minimumSignatureThreshold_public(setSize), setSize); + beefyValidatorProofFile = string.concat(vm.projectRoot(), "/test/data/beefy-final-proof.json"); + beefyValidatorProofRaw = vm.readFile(beefyValidatorProofFile); + + beefyFinalBitFieldFile = string.concat(vm.projectRoot(), "/test/data/beefy-final-bitfield.json"); + + blockNumber = uint32(beefyCommitmentRaw.readUint(".params.commitment.blockNumber")); + setId = uint32(beefyCommitmentRaw.readUint(".params.commitment.validatorSetID")); + commitHash = beefyCommitmentRaw.readBytes32(".commitmentHash"); + + setSize = uint32(beefyValidatorSetRaw.readUint(".validatorSetSize")); + root = beefyValidatorSetRaw.readBytes32(".validatorRoot"); + bitSetArray = beefyValidatorSetRaw.readUintArray(".participants"); + absentBitSetArray = beefyValidatorSetRaw.readUintArray(".absentees"); - inputs[2] = "GenerateProofs"; - inputs[3] = Strings.toString(finalBitfield.length); - for (uint256 i = 0; i < finalBitfield.length; i++) { - inputs[i + 4] = Strings.toString(finalBitfield[i]); - } - BeefyClient.ValidatorProof[] memory proofs; - (root, proofs, mmrLeafProofs, mmrLeaf, leafProofOrder) = - abi.decode(vm.ffi(inputs), (bytes32, BeefyClient.ValidatorProof[], bytes32[], BeefyClient.MMRLeaf, uint256)); - // Cache finalValidatorProofs to storage in order to reuse in submitFinal later - for (uint256 i = 0; i < proofs.length; i++) { - finalValidatorProofs.push(proofs[i]); - } console.log("current validator's merkle root is: %s", Strings.toHexString(uint256(root), 32)); + + mmrRoot = beefyCommitmentRaw.readBytes32(".params.commitment.payload[0].data"); + mmrLeafProofs = beefyCommitmentRaw.readBytes32Array(".params.leafProof"); + leafProofOrder = beefyCommitmentRaw.readUint(".params.leafProofOrder"); + decodeMMRLeaf(); + + bitfield = beefyClient.createInitialBitfield(bitSetArray, setSize); + absentBitfield = beefyClient.createInitialBitfield(absentBitSetArray, setSize); + + loadFinalProofs(); } function initialize(uint32 _setId) public returns (BeefyClient.Commitment memory) { @@ -87,10 +98,70 @@ contract BeefyClientTest is Test { function printBitArray(uint256[] memory bits) private view { for (uint256 i = 0; i < bits.length; i++) { - console.log("bits index at %d is %x", i, bits[i]); + console.log("bits index at %d is %d", i, bits[i]); + } + } + + function loadFinalProofs() internal { + bytes memory proofRaw = beefyValidatorProofRaw.readBytes(".finalValidatorsProofRaw"); + BeefyClient.ValidatorProof[] memory proofs = abi.decode(proofRaw, (BeefyClient.ValidatorProof[])); + for (uint256 i = 0; i < proofs.length; i++) { + finalValidatorProofs.push(proofs[i]); } } + // Ideally should also update `finalValidatorProofs` with another round of ffi based on the `finalBitfield` here + // For simplicity we just use the proof previously cached + // still update `finalBitfield` here is to simulate more close to the real workflow and make gas estimation more accurate + function createFinalProofs() internal { + finalBitfield = beefyClient.createFinalBitfield(commitHash, bitfield); + } + + function commitPrevRandao() internal { + vm.prevrandao(bytes32(uint256(prevRandao))); + beefyClient.commitPrevRandao(commitHash); + } + + // Regenerate bitField file + function regenerateBitField() internal { + console.log("print initialBitField"); + printBitArray(bitfield); + prevRandao = uint32(vm.envOr("PREV_RANDAO", prevRandao)); + finalBitfield = + Bitfield.subsample(prevRandao, bitfield, beefyClient.minimumSignatureThreshold_public(setSize), setSize); + console.log("print finalBitField"); + printBitArray(finalBitfield); + + string memory finalBitFieldRaw = ""; + finalBitFieldRaw = finalBitFieldRaw.serialize("finalBitFieldRaw", abi.encode(finalBitfield)); + + string memory finaliBitFieldStr = ""; + finaliBitFieldStr = finaliBitFieldStr.serialize("finalBitField", finalBitfield); + + string memory output = finalBitFieldRaw.serialize("final", finaliBitFieldStr); + + vm.writeJson(output, beefyFinalBitFieldFile); + } + + function decodeMMRLeaf() internal { + uint8 version = uint8(beefyCommitmentRaw.readUint(".params.leaf.version")); + uint32 parentNumber = uint32(beefyCommitmentRaw.readUint(".params.leaf.parentNumber")); + bytes32 parentHash = beefyCommitmentRaw.readBytes32(".params.leaf.parentHash"); + uint64 nextAuthoritySetID = uint64(beefyCommitmentRaw.readUint(".params.leaf.nextAuthoritySetID")); + uint32 nextAuthoritySetLen = uint32(beefyCommitmentRaw.readUint(".params.leaf.nextAuthoritySetLen")); + bytes32 nextAuthoritySetRoot = beefyCommitmentRaw.readBytes32(".params.leaf.nextAuthoritySetRoot"); + bytes32 parachainHeadsRoot = beefyCommitmentRaw.readBytes32(".params.leaf.parachainHeadsRoot"); + mmrLeaf = BeefyClient.MMRLeaf( + version, + parentNumber, + parentHash, + nextAuthoritySetID, + nextAuthoritySetLen, + nextAuthoritySetRoot, + parachainHeadsRoot + ); + } + function testSubmit() public returns (BeefyClient.Commitment memory) { BeefyClient.Commitment memory commitment = initialize(setId); @@ -99,10 +170,9 @@ contract BeefyClientTest is Test { // mine random delay blocks vm.roll(block.number + randaoCommitDelay); - // set difficulty as PrevRandao - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); beefyClient.submitFinal(commitment, bitfield, finalValidatorProofs); @@ -118,10 +188,9 @@ contract BeefyClientTest is Test { // mine random delay blocks vm.roll(block.number + randaoCommitDelay); - // set difficulty as PrevRandao - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); // make an invalid signature finalValidatorProofs[0].r = 0xb5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c; @@ -137,10 +206,9 @@ contract BeefyClientTest is Test { // mine random delay blocks vm.roll(block.number + randaoCommitDelay); - // set difficulty as PrevRandao - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); // make an invalid validator index finalValidatorProofs[0].index = 0; @@ -154,8 +222,11 @@ contract BeefyClientTest is Test { beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); - beefyClient.commitPrevRandao(commitHash); + + commitPrevRandao(); + + createFinalProofs(); + //submit again will be reverted with StaleCommitment vm.expectRevert(BeefyClient.StaleCommitment.selector); beefyClient.submitFinal(commitment, bitfield, finalValidatorProofs); @@ -168,9 +239,9 @@ contract BeefyClientTest is Test { vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); // invalid bitfield here bitfield[0] = 0; @@ -182,6 +253,7 @@ contract BeefyClientTest is Test { BeefyClient.Commitment memory commitment = initialize(setId); beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); + // reverted without commit PrevRandao vm.expectRevert(BeefyClient.PrevRandaoNotCaptured.selector); beefyClient.submitFinal(commitment, bitfield, finalValidatorProofs); @@ -193,12 +265,12 @@ contract BeefyClientTest is Test { beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); // reverted for commit PrevRandao too early vm.expectRevert(BeefyClient.WaitPeriodNotOver.selector); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); // reverted for commit PrevRandao too late vm.roll(block.number + randaoCommitDelay + randaoCommitExpiration + 1); vm.expectRevert(BeefyClient.TicketExpired.selector); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); } function testSubmitFailForPrevRandaoCapturedMoreThanOnce() public { @@ -206,11 +278,10 @@ contract BeefyClientTest is Test { beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); vm.expectRevert(BeefyClient.PrevRandaoAlreadyCaptured.selector); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); } function testSubmitWithHandover() public { @@ -221,9 +292,9 @@ contract BeefyClientTest is Test { vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); beefyClient.submitFinalWithHandover( commitment, bitfield, finalValidatorProofs, mmrLeaf, mmrLeafProofs, leafProofOrder @@ -244,15 +315,16 @@ contract BeefyClientTest is Test { } function testSubmitWithHandoverFailStaleCommitment() public { - BeefyClient.Commitment memory commitment = testSubmit(); + BeefyClient.Commitment memory commitment = initialize(setId - 1); + beefyClient.setLatestBeefyBlock(blockNumber); beefyClient.submitInitialWithHandover(commitment, bitfield, finalValidatorProofs[0]); vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); vm.expectRevert(BeefyClient.StaleCommitment.selector); beefyClient.submitFinalWithHandover( @@ -279,10 +351,8 @@ contract BeefyClientTest is Test { function testCreateInitialBitfield() public { initialize(setId); uint256[] memory initialBitfield = beefyClient.createInitialBitfield(bitSetArray, setSize); - assertTrue(initialBitfield.length == 2); + assertTrue(initialBitfield.length == (setSize + 255) / 256); printBitArray(initialBitfield); - assertEq(initialBitfield[0], 0xd9fbb69bb8dfe46bffd2fd7feefffb185aef39fafcec0beba6db619efad1f6db); - assertEq(initialBitfield[1], 0x7f76cee2a3f); } function testCreateInitialBitfieldInvalid() public { @@ -295,8 +365,7 @@ contract BeefyClientTest is Test { BeefyClient.Commitment memory commitment = initialize(setId); beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); uint256[] memory finalBits = beefyClient.createFinalBitfield(commitHash, bitfield); assertTrue(Bitfield.countSetBits(finalBits) < Bitfield.countSetBits(bitfield)); @@ -306,8 +375,7 @@ contract BeefyClientTest is Test { BeefyClient.Commitment memory commitment = initialize(setId); beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); // make invalid bitfield not same as initialized bitfield[0] = 0; @@ -318,9 +386,11 @@ contract BeefyClientTest is Test { function testSubmitFailWithInvalidValidatorSet() public { BeefyClient.Commitment memory commitment = initialize(setId); beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); + vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); + + createFinalProofs(); //reinitialize with next validator set initialize(setId + 1); @@ -336,10 +406,9 @@ contract BeefyClientTest is Test { beefyClient.submitInitialWithHandover(commitment, bitfield, finalValidatorProofs[0]); vm.roll(block.number + randaoCommitDelay); + commitPrevRandao(); - vm.prevrandao(bytes32(uint256(difficulty))); - - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); //reinitialize with next validator set initialize(setId); @@ -353,10 +422,14 @@ contract BeefyClientTest is Test { function testSubmitFailWithInvalidTicket() public { BeefyClient.Commitment memory commitment = initialize(setId); beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); + vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); - beefyClient.commitPrevRandao(commitHash); + commitPrevRandao(); + + createFinalProofs(); + // Changing the commitment changes its hash, so the ticket can't be found. + // A zero value ticket is returned in this case, because submitInitial hasn't run for this commitment. BeefyClient.Commitment memory _commitment = BeefyClient.Commitment(blockNumber, setId + 1, commitment.payload); //submit will be reverted with InvalidTicket vm.expectRevert(BeefyClient.InvalidTicket.selector); @@ -371,10 +444,12 @@ contract BeefyClientTest is Test { vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); + vm.prevrandao(bytes32(uint256(prevRandao))); beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); + //construct nextAuthoritySetID with a wrong value mmrLeaf.nextAuthoritySetID = setId; //submit will be reverted with InvalidCommitment @@ -392,9 +467,9 @@ contract BeefyClientTest is Test { vm.roll(block.number + randaoCommitDelay); - vm.prevrandao(bytes32(uint256(difficulty))); + commitPrevRandao(); - beefyClient.commitPrevRandao(commitHash); + createFinalProofs(); //construct parentNumber with a wrong value mmrLeaf.parentNumber = 1; @@ -413,4 +488,22 @@ contract BeefyClientTest is Test { vm.expectRevert(BeefyClient.NotEnoughClaims.selector); beefyClient.submitInitial(commitment, initialBits, finalValidatorProofs[0]); } + + function testSubmitInitialFailWithIncorrectValidatorSet() public { + BeefyClient.Commitment memory commitment = initialize(setId); + + vm.expectRevert(BeefyClient.InvalidCommitment.selector); + beefyClient.submitInitialWithHandover(commitment, bitfield, finalValidatorProofs[0]); + } + + function testSubmitInitialHandoverFailWithIncorrectValidatorSet() public { + BeefyClient.Commitment memory commitment = initialize(setId - 1); + + vm.expectRevert(BeefyClient.InvalidCommitment.selector); + beefyClient.submitInitial(commitment, bitfield, finalValidatorProofs[0]); + } + + function testRegenerateBitField() public { + regenerateBitField(); + } } diff --git a/contracts/test/Gateway.t.sol b/contracts/test/Gateway.t.sol new file mode 100644 index 0000000000000..e1aaf5a213b3e --- /dev/null +++ b/contracts/test/Gateway.t.sol @@ -0,0 +1,653 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {Strings} from "openzeppelin/utils/Strings.sol"; +import {console} from "forge-std/console.sol"; + +import {BeefyClient} from "../src/BeefyClient.sol"; + +import {IGateway} from "../src/interfaces/IGateway.sol"; +import {IInitializable} from "../src/interfaces/IInitializable.sol"; +import {Gateway} from "../src/Gateway.sol"; +import {GatewayMock, GatewayV2} from "./mocks/GatewayMock.sol"; + +import {GatewayProxy} from "../src/GatewayProxy.sol"; + +import {AgentExecutor} from "../src/AgentExecutor.sol"; +import {Agent} from "../src/Agent.sol"; +import {Verification} from "../src/Verification.sol"; +import {Assets} from "../src/Assets.sol"; +import {SubstrateTypes} from "./../src/SubstrateTypes.sol"; + +import {NativeTransferFailed} from "../src/utils/SafeTransfer.sol"; + +import {AgentExecuteCommand, InboundMessage, OperatingMode, ParaID, Config, Command} from "../src/Types.sol"; + +import {WETH9} from "canonical-weth/WETH9.sol"; + +contract GatewayTest is Test { + event InboundMessageDispatched(ParaID indexed origin, uint64 nonce, bool result); + event OutboundMessageAccepted(ParaID indexed dest, uint64 nonce, bytes payload); + event NativeTokensUnlocked(address token, address recipient, uint256 amount); + event TokenRegistrationSent(address token); + event TokenSent( + address indexed sender, address indexed token, ParaID destinationChain, bytes destinationAddress, uint128 amount + ); + event AgentCreated(bytes32 agentID, address agent); + event ChannelCreated(ParaID indexed paraID); + event ChannelUpdated(ParaID indexed paraID); + + event Upgraded(address indexed implementation); + + ParaID public bridgeHubParaID = ParaID.wrap(1001); + bytes32 public bridgeHubAgentID = keccak256("1001"); + address public bridgeHubAgent; + + ParaID public assetHubParaID = ParaID.wrap(1002); + bytes32 public assetHubAgentID = keccak256("1002"); + address public assetHubAgent; + + address public relayer; + + bytes32[] public proof = [bytes32(0x2f9ee6cfdf244060dc28aa46347c5219e303fc95062dd672b4e406ca5c29764b)]; + bytes public parachainHeaderProof = bytes("validProof"); + + GatewayMock public gatewayLogic; + GatewayProxy public gateway; + + WETH9 public token; + + address public account1; + address public account2; + + uint256 public constant DISPATCH_GAS = 500_000; + + uint256 public defaultFee = 1 ether; + uint256 public defaultReward = 1 ether; + uint256 public registerNativeTokenFee = 1 ether; + uint256 public sendNativeTokenFee = 1 ether; + + function setUp() public { + AgentExecutor executor = new AgentExecutor(); + gatewayLogic = new GatewayMock( + address(0), + address(executor), + DISPATCH_GAS, + bridgeHubParaID, + bridgeHubAgentID, + assetHubParaID, + assetHubAgentID, + bytes2(0x3500) + ); + gateway = new GatewayProxy( + address(gatewayLogic), + abi.encode( + defaultFee, + defaultReward, + registerNativeTokenFee, + sendNativeTokenFee + ) + ); + + bridgeHubAgent = IGateway(address(gateway)).agentOf(bridgeHubAgentID); + assetHubAgent = IGateway(address(gateway)).agentOf(assetHubAgentID); + + // fund the message relayer account + relayer = makeAddr("relayer"); + + // Features + + token = new WETH9(); + + account1 = makeAddr("account1"); + account2 = makeAddr("account2"); + + // create tokens for account 1 + hoax(account1); + token.deposit{value: 500}(); + + // create tokens for account 2 + token.deposit{value: 500}(); + } + + function makeCreateAgentCommand() public pure returns (Command, bytes memory) { + return (Command.CreateAgent, abi.encode((keccak256("6666")))); + } + + function makeMockProof() public pure returns (Verification.Proof memory) { + return Verification.Proof({ + header: Verification.ParachainHeader({ + parentHash: bytes32(0), + number: 0, + stateRoot: bytes32(0), + extrinsicsRoot: bytes32(0), + digestItems: new Verification.DigestItem[](0) + }), + headProof: Verification.HeadProof({pos: 0, width: 0, proof: new bytes32[](0)}), + leafPartial: Verification.MMRLeafPartial({ + version: 0, + parentNumber: 0, + parentHash: bytes32(0), + nextAuthoritySetID: 0, + nextAuthoritySetLen: 0, + nextAuthoritySetRoot: 0 + }), + leafProof: new bytes32[](0), + leafProofOrder: 0 + }); + } + + /** + * Message Verification + */ + + function testSubmitHappyPath() public { + deal(bridgeHubAgent, 50 ether); + + (Command command, bytes memory params) = makeCreateAgentCommand(); + + // Expect the gateway to emit `InboundMessageDispatched` + vm.expectEmit(true, false, false, false); + emit InboundMessageDispatched(bridgeHubParaID, 1, true); + + hoax(relayer, 1 ether); + IGateway(address(gateway)).submitInbound( + InboundMessage(bridgeHubParaID, 1, command, params), proof, makeMockProof() + ); + } + + function testSubmitFailInvalidNonce() public { + deal(bridgeHubAgent, 50 ether); + + (Command command, bytes memory params) = makeCreateAgentCommand(); + + hoax(relayer, 1 ether); + IGateway(address(gateway)).submitInbound( + InboundMessage(bridgeHubParaID, 1, command, params), proof, makeMockProof() + ); + + // try to replay the message + vm.expectRevert(Gateway.InvalidNonce.selector); + hoax(relayer, 1 ether); + IGateway(address(gateway)).submitInbound( + InboundMessage(bridgeHubParaID, 1, command, params), proof, makeMockProof() + ); + } + + function testSubmitFailInvalidChannel() public { + (Command command,) = makeCreateAgentCommand(); + + vm.expectRevert(Gateway.ChannelDoesNotExist.selector); + hoax(relayer); + IGateway(address(gateway)).submitInbound( + InboundMessage(ParaID.wrap(42), 1, command, ""), proof, makeMockProof() + ); + } + + /** + * Fees & Rewards + */ + + // Message relayer should be rewarded from the agent for a channel + function testRelayerRewardedFromAgent() public { + deal(bridgeHubAgent, 50 ether); + + (Command command, bytes memory params) = makeCreateAgentCommand(); + + hoax(relayer, 1 ether); + IGateway(address(gateway)).submitInbound( + InboundMessage(bridgeHubParaID, 1, command, params), proof, makeMockProof() + ); + + assertEq(address(bridgeHubAgent).balance, 49 ether); + assertEq(relayer.balance, 2 ether); + } + + // In this case, the agent has no funds to reward the relayer + function testRelayerNotRewarded() public { + (Command command, bytes memory params) = makeCreateAgentCommand(); + + vm.expectRevert(NativeTransferFailed.selector); + hoax(relayer, 1 ether); + IGateway(address(gateway)).submitInbound( + InboundMessage(bridgeHubParaID, 1, command, params), proof, makeMockProof() + ); + + assertEq(address(bridgeHubAgent).balance, 0 ether); + assertEq(relayer.balance, 1 ether); + } + + // Users should pay fees to send outbound messages + function testUserPaysFees() public { + // Create a mock user + address user = makeAddr("user"); + deal(address(token), user, 1); + + // Let gateway lock up to 1 tokens + hoax(user); + token.approve(address(gateway), 1); + + hoax(user, 2 ether); + IGateway(address(gateway)).sendToken{value: 2 ether}(address(token), ParaID.wrap(0), "", 1); + + assertEq(user.balance, 0 ether); + } + + // User doesn't have enough funds to send message + function testUserDoesNotProvideEnoughFees() public { + // Create a mock user + address user = makeAddr("user"); + deal(address(token), user, 1); + + // Let gateway lock up to 1 tokens + hoax(user); + token.approve(address(gateway), 1); + + vm.expectRevert(Gateway.FeePaymentToLow.selector); + hoax(user, 2 ether); + IGateway(address(gateway)).sendToken{value: 0.5 ether}(address(token), ParaID.wrap(0), "", 1); + + assertEq(user.balance, 2 ether); + } + + /** + * Handlers + */ + + function testAgentExecution() public { + token.transfer(address(assetHubAgent), 1); + + Gateway.AgentExecuteParams memory params = Gateway.AgentExecuteParams({ + agentID: assetHubAgentID, + payload: abi.encode(AgentExecuteCommand.TransferToken, abi.encode(address(token), address(this), 1)) + }); + + GatewayMock(address(gateway)).agentExecutePublic(abi.encode(params)); + } + + function testAgentExecutionBadOrigin() public { + Gateway.AgentExecuteParams memory params = Gateway.AgentExecuteParams({ + agentID: bytes32(0), + payload: abi.encode(keccak256("transferNativeToken"), abi.encode(address(token), address(this), 1)) + }); + + vm.expectRevert(Gateway.AgentDoesNotExist.selector); + GatewayMock(address(gateway)).agentExecutePublic(abi.encode(params)); + } + + function testAgentExecutionBadPayload() public { + Gateway.AgentExecuteParams memory params = Gateway.AgentExecuteParams({agentID: assetHubAgentID, payload: ""}); + + vm.expectRevert(Gateway.InvalidAgentExecutionPayload.selector); + GatewayMock(address(gateway)).agentExecutePublic(abi.encode(params)); + } + + function testCreateAgent() public { + bytes32 agentID = keccak256("123"); + Gateway.CreateAgentParams memory params = Gateway.CreateAgentParams({agentID: agentID}); + + vm.expectEmit(false, false, false, false, address(gateway)); + emit AgentCreated(agentID, address(0)); + + GatewayMock(address(gateway)).createAgentPublic(abi.encode(params)); + } + + function testCreateAgentAlreadyCreated() public { + bytes32 agentID = keccak256("123"); + Gateway.CreateAgentParams memory params = Gateway.CreateAgentParams({agentID: agentID}); + + GatewayMock(address(gateway)).createAgentPublic(abi.encode(params)); + + vm.expectRevert(Gateway.AgentAlreadyCreated.selector); + GatewayMock(address(gateway)).createAgentPublic(abi.encode(params)); + } + + function testCreateChannel() public { + ParaID paraID = ParaID.wrap(3042); + bytes32 agentID = keccak256("3042"); + + GatewayMock(address(gateway)).createAgentPublic(abi.encode(Gateway.CreateAgentParams({agentID: agentID}))); + + Gateway.CreateChannelParams memory params = Gateway.CreateChannelParams({paraID: paraID, agentID: agentID}); + + vm.expectEmit(true, false, false, true); + emit ChannelCreated(paraID); + GatewayMock(address(gateway)).createChannelPublic(abi.encode(params)); + } + + function testCreateChannelFailsAgentDoesNotExist() public { + ParaID paraID = ParaID.wrap(3042); + bytes32 agentID = keccak256("3042"); + + Gateway.CreateChannelParams memory params = Gateway.CreateChannelParams({paraID: paraID, agentID: agentID}); + + vm.expectRevert(Gateway.AgentDoesNotExist.selector); + GatewayMock(address(gateway)).createChannelPublic(abi.encode(params)); + } + + function testCreateChannelFailsChannelAlreadyExists() public { + ParaID paraID = ParaID.wrap(3042); + bytes32 agentID = keccak256("3042"); + + GatewayMock(address(gateway)).createAgentPublic(abi.encode(Gateway.CreateAgentParams({agentID: agentID}))); + + Gateway.CreateChannelParams memory params = Gateway.CreateChannelParams({paraID: paraID, agentID: agentID}); + + GatewayMock(address(gateway)).createChannelPublic(abi.encode(params)); + + vm.expectRevert(Gateway.ChannelAlreadyCreated.selector); + GatewayMock(address(gateway)).createChannelPublic(abi.encode(params)); + } + + function testUpdateChannel() public { + bytes memory params = abi.encode( + Gateway.UpdateChannelParams({ + paraID: assetHubParaID, + mode: OperatingMode.RejectingOutboundMessages, + fee: 2 ether, + reward: 2 ether + }) + ); + + vm.expectEmit(true, false, false, true); + emit ChannelUpdated(assetHubParaID); + GatewayMock(address(gateway)).updateChannelPublic(params); + + (uint256 fee, uint256 reward) = IGateway(address(gateway)).channelFeeRewardOf(assetHubParaID); + assertEq(fee, 2 ether); + assertEq(reward, 2 ether); + } + + function testUpdateChannelFailDoesNotExist() public { + bytes memory params = abi.encode( + Gateway.UpdateChannelParams({ + paraID: ParaID.wrap(5956), + mode: OperatingMode.RejectingOutboundMessages, + fee: 2 ether, + reward: 2 ether + }) + ); + + vm.expectRevert(Gateway.ChannelDoesNotExist.selector); + GatewayMock(address(gateway)).updateChannelPublic(params); + } + + function testUpdateChannelSanityChecksForBridgeHubChannel() public { + bytes memory params = abi.encode( + Gateway.UpdateChannelParams({ + paraID: bridgeHubParaID, + mode: OperatingMode.Normal, + fee: 100000000 ether, + reward: 100000000 ether + }) + ); + + vm.expectRevert(Gateway.InvalidChannelUpdate.selector); + GatewayMock(address(gateway)).updateChannelPublic(params); + } + + function testUpgrade() public { + // Upgrade to this new logic contract + GatewayV2 newLogic = new GatewayV2(); + + Gateway.UpgradeParams memory params = Gateway.UpgradeParams({ + impl: address(newLogic), + implCodeHash: address(newLogic).codehash, + initParams: abi.encode(42) + }); + + // Expect the gateway to emit `Upgraded` + vm.expectEmit(true, false, false, false); + emit Upgraded(address(newLogic)); + + GatewayMock(address(gateway)).upgradePublic(abi.encode(params)); + + // Verify that the GatewayV2.setup was called + assertEq(GatewayV2(address(gateway)).getValue(), 42); + } + + function testUpgradeFailOnInitializationFailure() public { + GatewayV2 newLogic = new GatewayV2(); + + Gateway.UpgradeParams memory params = Gateway.UpgradeParams({ + impl: address(newLogic), + implCodeHash: address(newLogic).codehash, + initParams: abi.encode(666) + }); + + vm.expectRevert(IInitializable.InitializationFailed.selector); + GatewayMock(address(gateway)).upgradePublic(abi.encode(params)); + } + + function testUpgradeFailCodeHashMismatch() public { + GatewayV2 newLogic = new GatewayV2(); + + Gateway.UpgradeParams memory params = + Gateway.UpgradeParams({impl: address(newLogic), implCodeHash: bytes32(0), initParams: abi.encode(42)}); + + vm.expectRevert(Gateway.InvalidCodeHash.selector); + GatewayMock(address(gateway)).upgradePublic(abi.encode(params)); + } + + function testSetOperatingMode() public { + Gateway.SetOperatingModeParams memory params = + Gateway.SetOperatingModeParams({mode: OperatingMode.RejectingOutboundMessages}); + + OperatingMode mode = IGateway(address(gateway)).operatingMode(); + assertEq(uint256(mode), 0); + + GatewayMock(address(gateway)).setOperatingModePublic(abi.encode(params)); + + mode = IGateway(address(gateway)).operatingMode(); + assertEq(uint256(mode), 1); + } + + function testWithdrawAgentFunds() public { + deal(assetHubAgent, 50 ether); + + address recipient = makeAddr("recipient"); + + bytes memory params = abi.encode( + Gateway.TransferNativeFromAgentParams({agentID: assetHubAgentID, recipient: recipient, amount: 3 ether}) + ); + + GatewayMock(address(gateway)).transferNativeFromAgentPublic(params); + + assertEq(assetHubAgent.balance, 47 ether); + assertEq(recipient.balance, 3 ether); + } + + /** + * Assets + */ + + function testRegisterToken() public { + vm.expectEmit(false, false, false, true); + emit TokenRegistrationSent(address(token)); + + vm.expectEmit(true, false, false, false); + emit OutboundMessageAccepted( + assetHubParaID, 1, SubstrateTypes.RegisterToken(address(gateway), address(token), bytes2(0x3500)) + ); + + IGateway(address(gateway)).registerToken{value: 2 ether}(address(token)); + } + + function testSendTokenAddress32() public { + // Let gateway lock up to 1 tokens + token.approve(address(gateway), 1); + + // Multilocation for recipient + ParaID destPara = ParaID.wrap(2043); + bytes32 destAddress = keccak256("/Alice"); + + vm.expectEmit(true, true, false, true); + emit TokenSent(address(this), address(token), destPara, abi.encodePacked(destAddress), 1); + + // Expect the gateway to emit `OutboundMessageAccepted` + vm.expectEmit(true, false, false, false); + emit OutboundMessageAccepted( + assetHubParaID, 1, SubstrateTypes.SendToken(address(gateway), address(token), destPara, destAddress, 1) + ); + + IGateway(address(gateway)).sendToken{value: 2 ether}(address(token), destPara, destAddress, 1); + } + + function testSendTokenAddress32ToAssetHub() public { + // Let gateway lock up to 1 tokens + token.approve(address(gateway), 1); + + // Multilocation for recipient + ParaID destPara = assetHubParaID; + bytes32 destAddress = keccak256("/Alice"); + + vm.expectEmit(true, true, false, true); + emit TokenSent(address(this), address(token), destPara, abi.encodePacked(destAddress), 1); + + // Expect the gateway to emit `OutboundMessageAccepted` + vm.expectEmit(true, false, false, false); + emit OutboundMessageAccepted( + assetHubParaID, 1, SubstrateTypes.SendToken(address(gateway), address(token), destAddress, 1) + ); + + IGateway(address(gateway)).sendToken{value: 2 ether}(address(token), destPara, destAddress, 1); + } + + function testSendTokenAddress20() public { + // Let gateway lock up to 1 tokens + token.approve(address(gateway), 1); + + // Multilocation for recipient + ParaID destPara = ParaID.wrap(2043); + address destAddress = makeAddr("/Alice"); + + vm.expectEmit(true, true, false, true); + emit TokenSent(address(this), address(token), destPara, abi.encodePacked(destAddress), 1); + + // Expect the gateway to emit `OutboundMessageAccepted` + vm.expectEmit(true, false, false, false); + emit OutboundMessageAccepted(assetHubParaID, 1, hex""); + + IGateway(address(gateway)).sendToken{value: 2 ether}(address(token), destPara, destAddress, 1); + } + + function testSendTokenAddress20FailsInvalidDestination() public { + // Let gateway lock up to 1 tokens + token.approve(address(gateway), 1); + + ParaID destPara = assetHubParaID; + address destAddress = makeAddr("/Alice"); + + // Should fail to send tokens to AssetHub + vm.expectRevert(Assets.InvalidDestination.selector); + IGateway(address(gateway)).sendToken{value: 2 ether}(address(token), destPara, destAddress, 1); + } + + /** + * Operating Modes + */ + + function testDisableOutboundMessaging() public { + // Let gateway lock up to 1 tokens + token.approve(address(gateway), 1); + + GatewayMock(address(gateway)).setOperatingModePublic( + abi.encode(Gateway.SetOperatingModeParams({mode: OperatingMode.RejectingOutboundMessages})) + ); + + OperatingMode mode = IGateway(address(gateway)).operatingMode(); + assertEq(uint256(mode), 1); + } + + function testDisableOutboundMessagingForChannel() public { + // Let gateway lock up to 1 tokens + token.approve(address(gateway), 1); + + GatewayMock(address(gateway)).setOperatingModePublic( + abi.encode(Gateway.SetOperatingModeParams({mode: OperatingMode.Normal})) + ); + + bytes memory params = abi.encode( + Gateway.UpdateChannelParams({ + paraID: assetHubParaID, + mode: OperatingMode.RejectingOutboundMessages, + fee: 1 ether, + reward: 1 ether + }) + ); + GatewayMock(address(gateway)).updateChannelPublic(params); + + OperatingMode mode = IGateway(address(gateway)).channelOperatingModeOf(assetHubParaID); + assertEq(uint256(mode), 1); + + // Now all outbound messaging should be disabled + + vm.expectRevert(Gateway.Disabled.selector); + IGateway(address(gateway)).registerToken{value: 1 ether}(address(token)); + + vm.expectRevert(Gateway.Disabled.selector); + IGateway(address(gateway)).sendToken{value: 1 ether}(address(token), ParaID.wrap(0), "", 1); + } + + /** + * Misc checks + */ + + // Initialize function should not be externally callable on either proxy or implementation contract + function testInitializeNotExternallyCallable() public { + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).initialize(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + GatewayMock(address(gatewayLogic)).initialize(""); + } + + // Handler functions should not be externally callable + function testHandlersNotExternallyCallable() public { + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).agentExecute(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).createAgent(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).createChannel(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).updateChannel(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).setOperatingMode(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).upgrade(""); + + vm.expectRevert(Gateway.Unauthorized.selector); + Gateway(address(gateway)).transferNativeFromAgent(""); + } + + function testGetters() public { + IGateway gw = IGateway(address(gateway)); + + OperatingMode mode = gw.operatingMode(); + assertEq(uint256(mode), 0); + + OperatingMode channelMode = gw.channelOperatingModeOf(bridgeHubParaID); + assertEq(uint256(channelMode), 0); + + (uint256 fee, uint256 reward) = gw.channelFeeRewardOf(bridgeHubParaID); + assertEq(fee, 1 ether); + assertEq(reward, 1 ether); + + (uint64 inbound, uint64 outbound) = gw.channelNoncesOf(bridgeHubParaID); + assertEq(inbound, 0); + assertEq(outbound, 0); + + address agent = gw.agentOf(bridgeHubAgentID); + assertEq(agent, bridgeHubAgent); + + address implementation = gw.implementation(); + assertEq(implementation, address(gatewayLogic)); + } +} diff --git a/contracts/test/MMRProof.t.sol b/contracts/test/MMRProof.t.sol new file mode 100644 index 0000000000000..0fa64c6f58cec --- /dev/null +++ b/contracts/test/MMRProof.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +import {MMRProof} from "../src/utils/MMRProof.sol"; +import {MMRProofWrapper} from "./mocks/MMRProofWrapper.sol"; + +contract MMRProofTest is Test { + using stdJson for string; + + struct Fixture { + bytes32[] leaves; + Proof[] proofs; + bytes32 rootHash; + } + + struct Proof { + bytes32[] items; + uint256 order; + } + + bytes public fixtureData; + + MMRProofWrapper public wrapper; + + function setUp() public { + wrapper = new MMRProofWrapper(); + + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/test/data/mmr-fixture-data-15-leaves.json"); + //string memory json = vm.readFile(path); + fixtureData = vm.readFile(path).parseRaw(""); + } + + function fixture() public view returns (Fixture memory) { + return abi.decode(fixtureData, (Fixture)); + } + + function testVerifyLeafProof() public { + Fixture memory fix = fixture(); + + for (uint256 i = 0; i < fix.leaves.length; i++) { + assertTrue(wrapper.verifyLeafProof(fix.rootHash, fix.leaves[i], fix.proofs[i].items, fix.proofs[i].order)); + } + } + + function testVerifyLeafProofFailsExceededProofSize() public { + Fixture memory fix = fixture(); + + vm.expectRevert(MMRProof.ProofSizeExceeded.selector); + wrapper.verifyLeafProof(fix.rootHash, fix.leaves[0], new bytes32[](257), fix.proofs[0].order); + } +} diff --git a/contracts/test/ScaleCodec.t.sol b/contracts/test/ScaleCodec.t.sol new file mode 100644 index 0000000000000..51a8918183ba8 --- /dev/null +++ b/contracts/test/ScaleCodec.t.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {ScaleCodec} from "../src/utils/ScaleCodec.sol"; + +contract ScaleCodecTest is Test { + function testEncodeU256() public { + assertEq( + ScaleCodec.encodeU256(12063978950259949786323707366460749298097791896371638493358994162204017315152), + hex"504d8a21dd3868465c8c9f2898b7f014036935fa9a1488629b109d3d59f8ab1a" + ); + } + + function testEncodeU128() public { + assertEq(ScaleCodec.encodeU128(35452847761173902980759433963665451267), hex"036935fa9a1488629b109d3d59f8ab1a"); + } + + function testEncodeU64() public { + assertEq(ScaleCodec.encodeU64(1921902728173129883), hex"9b109d3d59f8ab1a"); + } + + function testEncodeU32() public { + assertEq(ScaleCodec.encodeU32(447477849), hex"59f8ab1a"); + } + + function testEncodeU16() public { + assertEq(ScaleCodec.encodeU16(6827), hex"ab1a"); + } + + function testEncodeCompactU32() public { + assertEq(ScaleCodec.encodeCompactU32(0), hex"00"); + assertEq(ScaleCodec.encodeCompactU32(63), hex"fc"); + assertEq(ScaleCodec.encodeCompactU32(64), hex"0101"); + assertEq(ScaleCodec.encodeCompactU32(16383), hex"fdff"); + assertEq(ScaleCodec.encodeCompactU32(16384), hex"02000100"); + assertEq(ScaleCodec.encodeCompactU32(1073741823), hex"feffffff"); + assertEq(ScaleCodec.encodeCompactU32(1073741824), hex"0300000040"); + assertEq(ScaleCodec.encodeCompactU32(type(uint32).max), hex"03ffffffff"); + } + + function testCheckedEncodeCompactU32() public { + assertEq(ScaleCodec.checkedEncodeCompactU32(type(uint32).max), hex"03ffffffff"); + + vm.expectRevert(ScaleCodec.UnsupportedCompactEncoding.selector); + ScaleCodec.checkedEncodeCompactU32(uint256(type(uint32).max) + 1); + } +} diff --git a/core/packages/contracts/test/ParachainClient.t.sol b/contracts/test/Verification.t.sol similarity index 61% rename from core/packages/contracts/test/ParachainClient.t.sol rename to contracts/test/Verification.t.sol index 5232d31cb6805..462d9e4ea50b9 100644 --- a/core/packages/contracts/test/ParachainClient.t.sol +++ b/contracts/test/Verification.t.sol @@ -1,41 +1,42 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; import "openzeppelin/utils/Strings.sol"; import "forge-std/Test.sol"; import "forge-std/console.sol"; -import {ScaleCodec} from "../src/ScaleCodec.sol"; +import {ScaleCodec} from "../src/utils/ScaleCodec.sol"; import {BeefyClientMock} from "./mocks/BeefyClientMock.sol"; -import {ParachainClient, ParachainClientMock} from "./mocks/ParachainClientMock.sol"; +import {Verification, VerificationWrapper} from "./mocks/VerificationWrapper.sol"; -contract ParachainClientTest is Test { - BeefyClientMock beefyClient; - ParachainClientMock parachainClient; +contract VerificationTest is Test { + BeefyClientMock public beefyClient; + VerificationWrapper public v; uint32 public constant BRIDGE_HUB_PARA_ID = 1013; + bytes4 public encodedParachainID; function setUp() public { beefyClient = new BeefyClientMock(3, 8); - parachainClient = new ParachainClientMock(beefyClient, BRIDGE_HUB_PARA_ID); + encodedParachainID = ScaleCodec.encodeU32(BRIDGE_HUB_PARA_ID); + v = new VerificationWrapper(); } function testCreateParachainHeaderMerkleLeaf() public { - ParachainClient.DigestItem[] memory digestItems = new ParachainClient.DigestItem[](3); - digestItems[0] = - ParachainClient.DigestItem({kind: 6, consensusEngineID: 0x61757261, data: hex"c1f05e0800000000"}); - digestItems[1] = ParachainClient.DigestItem({ + Verification.DigestItem[] memory digestItems = new Verification.DigestItem[](3); + digestItems[0] = Verification.DigestItem({kind: 6, consensusEngineID: 0x61757261, data: hex"c1f05e0800000000"}); + digestItems[1] = Verification.DigestItem({ kind: 4, consensusEngineID: 0x52505352, data: hex"73a902d5a4fa8fea942d01ad3c1dc32b51192c3a98c39fcc59299006ed391a5e2e005501" }); - digestItems[2] = ParachainClient.DigestItem({ + digestItems[2] = Verification.DigestItem({ kind: 5, consensusEngineID: 0x61757261, data: hex"fcfbfaf1ad15d24cb4980436c18aec6211e2255f648df0e05e73a7858fba8c31726925f1a825383d0d3cb590502b18978101a6391fbeef5ab53e14c05124188c" }); - ParachainClient.ParachainHeader memory header = ParachainClient.ParachainHeader({ + Verification.ParachainHeader memory header = Verification.ParachainHeader({ parentHash: 0x1df01d40273b074708115135fd7f76801ad4e4f1266a771a037962ee3a03259d, number: 866538, stateRoot: 0x7b2d59d4de7c629b55a9bc9b76d932616f2011a26f09b52da36e070d6a7eee0d, @@ -50,21 +51,21 @@ contract ParachainClientTest is Test { keccak256( bytes.concat( ScaleCodec.encodeU32(BRIDGE_HUB_PARA_ID), - ScaleCodec.encodeCompactUint(headerExpected.length), + ScaleCodec.encodeCompactU32(uint32(headerExpected.length)), headerExpected ) ), - parachainClient.createParachainHeaderMerkleLeaf_public(header) + v.createParachainHeaderMerkleLeaf(encodedParachainID, header) ); } function testCreateParachainHeaderMerkleFailInvalidHeader() public { - ParachainClient.DigestItem[] memory digestItems = new ParachainClient.DigestItem[](1); + Verification.DigestItem[] memory digestItems = new Verification.DigestItem[](1); // Create an invalid digest item digestItems[0] = - ParachainClient.DigestItem({kind: 666, consensusEngineID: 0x61757261, data: hex"c1f05e0800000000"}); + Verification.DigestItem({kind: 666, consensusEngineID: 0x61757261, data: hex"c1f05e0800000000"}); - ParachainClient.ParachainHeader memory header = ParachainClient.ParachainHeader({ + Verification.ParachainHeader memory header = Verification.ParachainHeader({ parentHash: 0x1df01d40273b074708115135fd7f76801ad4e4f1266a771a037962ee3a03259d, number: 866538, stateRoot: 0x7b2d59d4de7c629b55a9bc9b76d932616f2011a26f09b52da36e070d6a7eee0d, @@ -72,31 +73,30 @@ contract ParachainClientTest is Test { digestItems: digestItems }); - vm.expectRevert(ParachainClient.InvalidParachainHeader.selector); - parachainClient.createParachainHeaderMerkleLeaf_public(header); + vm.expectRevert(Verification.InvalidParachainHeader.selector); + v.createParachainHeaderMerkleLeaf(encodedParachainID, header); } function testIsCommitmentInHeaderDigest() public view { - ParachainClient.DigestItem[] memory digestItems = new ParachainClient.DigestItem[](4); - digestItems[0] = - ParachainClient.DigestItem({kind: 6, consensusEngineID: 0x61757261, data: hex"c1f05e0800000000"}); - digestItems[1] = ParachainClient.DigestItem({ + Verification.DigestItem[] memory digestItems = new Verification.DigestItem[](4); + digestItems[0] = Verification.DigestItem({kind: 6, consensusEngineID: 0x61757261, data: hex"c1f05e0800000000"}); + digestItems[1] = Verification.DigestItem({ kind: 4, consensusEngineID: 0x52505352, data: hex"73a902d5a4fa8fea942d01ad3c1dc32b51192c3a98c39fcc59299006ed391a5e2e005501" }); - digestItems[2] = ParachainClient.DigestItem({ + digestItems[2] = Verification.DigestItem({ kind: 0, consensusEngineID: 0x00000000, data: hex"b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" }); - digestItems[3] = ParachainClient.DigestItem({ + digestItems[3] = Verification.DigestItem({ kind: 5, consensusEngineID: 0x61757261, data: hex"fcfbfaf1ad15d24cb4980436c18aec6211e2255f648df0e05e73a7858fba8c31726925f1a825383d0d3cb590502b18978101a6391fbeef5ab53e14c05124188c" }); - ParachainClient.ParachainHeader memory header = ParachainClient.ParachainHeader({ + Verification.ParachainHeader memory header = Verification.ParachainHeader({ parentHash: 0x1df01d40273b074708115135fd7f76801ad4e4f1266a771a037962ee3a03259d, number: 866538, stateRoot: 0x7b2d59d4de7c629b55a9bc9b76d932616f2011a26f09b52da36e070d6a7eee0d, @@ -105,18 +105,12 @@ contract ParachainClientTest is Test { }); // Digest item at index 2 contains the commitment - assert( - parachainClient.isCommitmentInHeaderDigest_public( - 0xb5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, header - ) - ); + assert(v.isCommitmentInHeaderDigest(0xb5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, header)); // Now remove the commitment from the parachain header header.digestItems[2] = header.digestItems[3]; assert( - !parachainClient.isCommitmentInHeaderDigest_public( - 0xb5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, header - ) + !v.isCommitmentInHeaderDigest(0xb5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, header) ); } } diff --git a/core/packages/contracts/test/data/beefy-commitment.json b/contracts/test/data/beefy-commitment.json similarity index 100% rename from core/packages/contracts/test/data/beefy-commitment.json rename to contracts/test/data/beefy-commitment.json diff --git a/contracts/test/data/beefy-final-bitfield.json b/contracts/test/data/beefy-final-bitfield.json new file mode 100644 index 0000000000000..c25416428160c --- /dev/null +++ b/contracts/test/data/beefy-final-bitfield.json @@ -0,0 +1,9 @@ +{ + "final": { + "finalBitField": [ + 3618502792036124440576582696777723666402714743437477508623650775118001471488, + 17179869200 + ], + "finalBitFieldRaw": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000208000000200000000800000800002000004000000008000000000000800000000000000000000000000000000000000000000000000000000000000400000010" + } +} \ No newline at end of file diff --git a/contracts/test/data/beefy-final-proof.json b/contracts/test/data/beefy-final-proof.json new file mode 100644 index 0000000000000..f613d386f7996 --- /dev/null +++ b/contracts/test/data/beefy-final-proof.json @@ -0,0 +1,840 @@ +{ + "finalValidatorsProof": [ + { + "v": 27, + "r": { + "0": 56, + "1": 87, + "2": 185, + "3": 73, + "4": 67, + "5": 171, + "6": 245, + "7": 94, + "8": 216, + "9": 127, + "10": 175, + "11": 120, + "12": 201, + "13": 220, + "14": 0, + "15": 229, + "16": 248, + "17": 72, + "18": 10, + "19": 218, + "20": 67, + "21": 207, + "22": 40, + "23": 90, + "24": 154, + "25": 131, + "26": 132, + "27": 3, + "28": 69, + "29": 219, + "30": 47, + "31": 222 + }, + "s": { + "0": 79, + "1": 142, + "2": 79, + "3": 87, + "4": 204, + "5": 67, + "6": 94, + "7": 173, + "8": 56, + "9": 222, + "10": 4, + "11": 96, + "12": 32, + "13": 188, + "14": 17, + "15": 114, + "16": 127, + "17": 139, + "18": 236, + "19": 35, + "20": 246, + "21": 173, + "22": 67, + "23": 109, + "24": 188, + "25": 182, + "26": 97, + "27": 128, + "28": 139, + "29": 9, + "30": 201, + "31": 100 + }, + "index": 31, + "account": "0x5473090d3a9D7B984B31f2d36f2d004a9188796d", + "proof": [ + "0x2d3fe5fcf7e9b1559b73b0055d813911a135fd0f7311e5a69899cf420c418c9f", + "0x8df6a7abbefe9b2fe4e384876b71ec1eb90d23950c68b78df4e22909590d1930", + "0x7126a8044f997db28aaf469f8f66a8a4c09c25ab03c0b902bf02618d54d5e86e", + "0x325666c5a681388f68098fa3270d9f8b05de0c3a929cf61ce2fff465db97ffa4", + "0xdf9973cc4b389edb18d204fb23baa094715a7f530e120a19fd643bd338f242ed", + "0x8c83332339cab7a6008352495919f7102dbe1cc4d6d243682565de39b33d4899", + "0xb8aefe65af72a69011a5539ab2d19e55a34db316d3b0235a2117d5b6fc42ffde", + "0xf804afe61ff1c61cdcb536df0f29b62f6ca8ae121863b66c826a2ee9823f3365", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 28, + "r": { + "0": 134, + "1": 9, + "2": 91, + "3": 10, + "4": 201, + "5": 18, + "6": 162, + "7": 237, + "8": 46, + "9": 123, + "10": 22, + "11": 151, + "12": 10, + "13": 238, + "14": 159, + "15": 92, + "16": 231, + "17": 239, + "18": 177, + "19": 133, + "20": 18, + "21": 232, + "22": 13, + "23": 64, + "24": 118, + "25": 196, + "26": 117, + "27": 15, + "28": 62, + "29": 114, + "30": 189, + "31": 234 + }, + "s": { + "0": 43, + "1": 50, + "2": 161, + "3": 46, + "4": 114, + "5": 133, + "6": 190, + "7": 78, + "8": 192, + "9": 73, + "10": 223, + "11": 154, + "12": 45, + "13": 43, + "14": 218, + "15": 183, + "16": 80, + "17": 240, + "18": 0, + "19": 224, + "20": 248, + "21": 12, + "22": 201, + "23": 15, + "24": 140, + "25": 156, + "26": 176, + "27": 115, + "28": 21, + "29": 239, + "30": 90, + "31": 143 + }, + "index": 83, + "account": "0xe11cEabDd29528aFFcC2f7936e0E80877CcF1E1A", + "proof": [ + "0x95f466dc7f9837f333cf284f84b3ef47d968203b93571d6e67379a55239bac68", + "0x1f22928e92219f9cbe815f7a2baa4b71238a975a4017f36fdbe7cc736cc77870", + "0x70e953d23047cbc07dc21fa318e1dd6851ccd19a5fed5976976a78236a66d647", + "0x7bc44cfe90425291d8c8808375892cb895a9dd67ffd994a74bb0985b7072d98b", + "0xe1f4f439878975a3e8cfc749957c8b204653fd135da9b547d302697138859613", + "0x03abdd191345b346cc826490fd23eb43349fab167ad091f4c48d9d2f6d70a540", + "0x2586b1acf8187086c42dd317785c79d85fb281987845a982517a5925ff9c7b2b", + "0xf804afe61ff1c61cdcb536df0f29b62f6ca8ae121863b66c826a2ee9823f3365", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 28, + "r": { + "0": 64, + "1": 6, + "2": 83, + "3": 215, + "4": 60, + "5": 41, + "6": 219, + "7": 174, + "8": 102, + "9": 105, + "10": 11, + "11": 249, + "12": 26, + "13": 87, + "14": 231, + "15": 130, + "16": 77, + "17": 156, + "18": 147, + "19": 87, + "20": 30, + "21": 24, + "22": 102, + "23": 36, + "24": 242, + "25": 231, + "26": 53, + "27": 186, + "28": 95, + "29": 250, + "30": 185, + "31": 13 + }, + "s": { + "0": 91, + "1": 174, + "2": 224, + "3": 47, + "4": 225, + "5": 90, + "6": 2, + "7": 244, + "8": 10, + "9": 31, + "10": 93, + "11": 248, + "12": 120, + "13": 190, + "14": 221, + "15": 70, + "16": 250, + "17": 85, + "18": 134, + "19": 27, + "20": 94, + "21": 7, + "22": 44, + "23": 146, + "24": 249, + "25": 76, + "26": 236, + "27": 105, + "28": 50, + "29": 142, + "30": 186, + "31": 228 + }, + "index": 118, + "account": "0xb79df9BBD3Cc5a316374d40a35898657e2D8e18E", + "proof": [ + "0x7df725da049349c532528abe804b608d47fd20993d68053fc1b3d6042ca0002b", + "0x2f3e8719554d71589ae679692ef3951fdaee3445126323eddf5edfbc78be6aa5", + "0xa44761bb661fd68431ba5962280d515d2e286060fac0a5893bf5c7a7bc4309d1", + "0x3669134efbdc64823fbca48af53f72ffb0dccdef81c3b0d35f804893d535e886", + "0x6eafa8fc9b0e67ab52141344ed25288a2bb3d158af038ea9ecc3c2ddf30f32e7", + "0x9c88a3c47b71bf6a0902cb29f0acc01a5e6b16f50d9030a2c6b6cc46aa3abfc8", + "0x2586b1acf8187086c42dd317785c79d85fb281987845a982517a5925ff9c7b2b", + "0xf804afe61ff1c61cdcb536df0f29b62f6ca8ae121863b66c826a2ee9823f3365", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 27, + "r": { + "0": 224, + "1": 135, + "2": 154, + "3": 30, + "4": 139, + "5": 155, + "6": 130, + "7": 154, + "8": 212, + "9": 156, + "10": 49, + "11": 92, + "12": 42, + "13": 95, + "14": 214, + "15": 238, + "16": 38, + "17": 118, + "18": 173, + "19": 164, + "20": 215, + "21": 173, + "22": 184, + "23": 227, + "24": 70, + "25": 46, + "26": 24, + "27": 67, + "28": 149, + "29": 27, + "30": 105, + "31": 53 + }, + "s": { + "0": 116, + "1": 62, + "2": 232, + "3": 154, + "4": 164, + "5": 74, + "6": 59, + "7": 107, + "8": 37, + "9": 5, + "10": 26, + "11": 123, + "12": 130, + "13": 173, + "14": 193, + "15": 237, + "16": 25, + "17": 228, + "18": 210, + "19": 146, + "20": 38, + "21": 158, + "22": 25, + "23": 61, + "24": 124, + "25": 175, + "26": 112, + "27": 125, + "28": 154, + "29": 83, + "30": 51, + "31": 184 + }, + "index": 141, + "account": "0xC66888DDEbd37D715B5278A86a35d58F0D9B90F4", + "proof": [ + "0x08b8935325ae43169b960e19bb8d97eadf46e3e881978aff6decf2cad2edd8d4", + "0x518211971ae9be734ef9576dc3a94f2e7a24cee2b67d158e6af5e6ede48b8e2b", + "0x1137b81220981703e7f8fb9c13d3052513b17f8fe0dc801500ea64b25eee49fe", + "0x42a0104a13de7b8090ba2326a97024c1157d88281804ce5fb85ea82abaf1eef4", + "0xe05e69cbeca48f72fd3d81601b5419215fb234ba3a76467e8cd973d335c9e83a", + "0xc72bd3c5ef89cc841cebd46ee834312bbb107ee0b90e729f93eb7ce924ea2d80", + "0x64aaad909501e44338a8a9191abc63f8def273fb9f03108864016a17cad259dc", + "0xf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 28, + "r": { + "0": 179, + "1": 36, + "2": 218, + "3": 96, + "4": 164, + "5": 120, + "6": 156, + "7": 156, + "8": 99, + "9": 187, + "10": 40, + "11": 126, + "12": 223, + "13": 152, + "14": 155, + "15": 65, + "16": 8, + "17": 19, + "18": 29, + "19": 41, + "20": 91, + "21": 200, + "22": 89, + "23": 208, + "24": 231, + "25": 49, + "26": 107, + "27": 101, + "28": 50, + "29": 85, + "30": 210, + "31": 147 + }, + "s": { + "0": 10, + "1": 0, + "2": 233, + "3": 251, + "4": 123, + "5": 27, + "6": 238, + "7": 177, + "8": 220, + "9": 145, + "10": 125, + "11": 6, + "12": 218, + "13": 69, + "14": 30, + "15": 43, + "16": 231, + "17": 225, + "18": 237, + "19": 255, + "20": 193, + "21": 56, + "22": 148, + "23": 175, + "24": 30, + "25": 97, + "26": 193, + "27": 172, + "28": 204, + "29": 18, + "30": 172, + "31": 129 + }, + "index": 163, + "account": "0x66a04195aCacaf002D88928B582f729E52655815", + "proof": [ + "0x0cd1ee823e290df8b9dff0067abab1eaed0749a7453852fffedbf62429be9608", + "0x4a77cc45d751eb4a541863939cdc472bd7179db4e9bce47aff72e11d53d824ca", + "0x136d1789bce723dc057eea270cb480ec6e3308e1fdffe9d1e9fdc26b673b37f1", + "0x68a649c5d1d5b44417b82100e8f3a87587a7affaadd64d88e6d5af06f3878c72", + "0xa907b494272792d0106ddc58923600fa00a366d0eb6bd7264a9fcea91d5585fb", + "0x137973435ae824f670344e596684069be579cc265fa6f74b78a23a04ef85d88d", + "0x64aaad909501e44338a8a9191abc63f8def273fb9f03108864016a17cad259dc", + "0xf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 27, + "r": { + "0": 217, + "1": 40, + "2": 246, + "3": 19, + "4": 235, + "5": 200, + "6": 153, + "7": 35, + "8": 151, + "9": 223, + "10": 220, + "11": 51, + "12": 133, + "13": 232, + "14": 230, + "15": 180, + "16": 222, + "17": 148, + "18": 220, + "19": 95, + "20": 75, + "21": 146, + "22": 222, + "23": 87, + "24": 153, + "25": 170, + "26": 4, + "27": 165, + "28": 156, + "29": 176, + "30": 154, + "31": 25 + }, + "s": { + "0": 34, + "1": 5, + "2": 53, + "3": 51, + "4": 59, + "5": 229, + "6": 167, + "7": 143, + "8": 165, + "9": 227, + "10": 165, + "11": 29, + "12": 103, + "13": 244, + "14": 135, + "15": 14, + "16": 156, + "17": 72, + "18": 101, + "19": 87, + "20": 252, + "21": 32, + "22": 26, + "23": 118, + "24": 193, + "25": 101, + "26": 6, + "27": 206, + "28": 221, + "29": 108, + "30": 71, + "31": 134 + }, + "index": 187, + "account": "0x85098Dfb29a8A71208fFE981886A33a2c3E3f2B2", + "proof": [ + "0xc90699ab2080cfb90faf611369b3270e75c46722954fb05ddc48ff4231d6bee3", + "0x6ba8a511b931a886b8547f75c94c89188aa817901edbcf4076d2e28c29cda4aa", + "0x0268cdd4761f48b12c987142c2f89dace26b4cfea9edef0e71a934a805d15794", + "0x2ba6746783167c393bea28563490ded0680108da88f6fd0245e8b8e18b1004fc", + "0x599a8674d32d090e93042776f9b7c43790c455091892e35deb595b5954a7471e", + "0x137973435ae824f670344e596684069be579cc265fa6f74b78a23a04ef85d88d", + "0x64aaad909501e44338a8a9191abc63f8def273fb9f03108864016a17cad259dc", + "0xf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 28, + "r": { + "0": 182, + "1": 143, + "2": 236, + "3": 153, + "4": 83, + "5": 159, + "6": 124, + "7": 131, + "8": 55, + "9": 248, + "10": 149, + "11": 146, + "12": 192, + "13": 249, + "14": 220, + "15": 178, + "16": 188, + "17": 55, + "18": 252, + "19": 191, + "20": 237, + "21": 211, + "22": 68, + "23": 227, + "24": 217, + "25": 130, + "26": 206, + "27": 37, + "28": 74, + "29": 117, + "30": 251, + "31": 84 + }, + "s": { + "0": 26, + "1": 86, + "2": 142, + "3": 125, + "4": 88, + "5": 205, + "6": 193, + "7": 220, + "8": 219, + "9": 54, + "10": 188, + "11": 152, + "12": 223, + "13": 132, + "14": 183, + "15": 68, + "16": 83, + "17": 176, + "18": 56, + "19": 251, + "20": 213, + "21": 39, + "22": 203, + "23": 185, + "24": 71, + "25": 88, + "26": 196, + "27": 8, + "28": 67, + "29": 30, + "30": 75, + "31": 73 + }, + "index": 221, + "account": "0x3b5F3d19020fb26367a6a0eA611CB0E7dE28DE33", + "proof": [ + "0x1b1b9ace3e2c1a1785ee845eed31a37e3d9dffdd2702868b18d8ff2a5b309ea5", + "0xe37762d4ee9ceac6ff6676f1cc9e062a81aa4dbcb60946f32f4d8b72c2b8cadd", + "0x6861b76364d1c3170f84724667f2dab3c206b1a2b3db9a5b1ca64ba233997c5f", + "0x85067ce849428405cf1b407341b9376d504e3ff593b00e4aae4f65e30a36db3c", + "0xa3e540d32650f8682146d5649323edcf497d1451d505914616d409a89efff9da", + "0x1bcc228cc309f83f90031fb5c788d2487eed6b8a12c98774d7a9c23c0cee17c6", + "0xdbf5e78cdca685e455240593bc327f715dbb1552bdcd7e5f821dc6cc41e2cfb0", + "0xf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 28, + "r": { + "0": 212, + "1": 212, + "2": 229, + "3": 193, + "4": 74, + "5": 51, + "6": 5, + "7": 76, + "8": 91, + "9": 138, + "10": 190, + "11": 156, + "12": 136, + "13": 149, + "14": 58, + "15": 239, + "16": 44, + "17": 134, + "18": 86, + "19": 122, + "20": 135, + "21": 254, + "22": 66, + "23": 82, + "24": 100, + "25": 4, + "26": 164, + "27": 136, + "28": 122, + "29": 77, + "30": 93, + "31": 177 + }, + "s": { + "0": 70, + "1": 4, + "2": 156, + "3": 172, + "4": 246, + "5": 28, + "6": 95, + "7": 220, + "8": 66, + "9": 221, + "10": 42, + "11": 224, + "12": 205, + "13": 242, + "14": 100, + "15": 86, + "16": 190, + "17": 149, + "18": 178, + "19": 218, + "20": 169, + "21": 130, + "22": 182, + "23": 95, + "24": 234, + "25": 54, + "26": 153, + "27": 29, + "28": 197, + "29": 235, + "30": 158, + "31": 247 + }, + "index": 251, + "account": "0x83694089d1e2FBD01c090a3198C64A9153D2F8Fa", + "proof": [ + "0x9fe76ba617982f9986fc59e8521171ebe81e0c7491d91521a0fe9a0b635af8a5", + "0x462f5f4793463267cac15dacb74be47bddc2f19985682e9a8dae06fbdcd60293", + "0x942ca9c53961d698e1d0cd11e72c60329679204ae7a8357a4b557f88f767aacd", + "0x638ed41e5e35db1049fe4794634692551b91f937358d0253016627fc3dbbf8a0", + "0xff0e576ff6a911efa30fd9002adcfa5d69f7e14818215b7fe0f22a1c22686161", + "0x8527ec55aceec37ad9c2b70e7e14ebe2c51994e496fcbedae2db5aedf4bd4a5e", + "0xdbf5e78cdca685e455240593bc327f715dbb1552bdcd7e5f821dc6cc41e2cfb0", + "0xf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d", + "0x73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0" + ] + }, + { + "v": 27, + "r": { + "0": 168, + "1": 227, + "2": 31, + "3": 135, + "4": 190, + "5": 211, + "6": 178, + "7": 184, + "8": 221, + "9": 77, + "10": 114, + "11": 7, + "12": 20, + "13": 115, + "14": 201, + "15": 102, + "16": 11, + "17": 140, + "18": 179, + "19": 253, + "20": 96, + "21": 41, + "22": 34, + "23": 121, + "24": 197, + "25": 161, + "26": 69, + "27": 165, + "28": 22, + "29": 200, + "30": 227, + "31": 189 + }, + "s": { + "0": 115, + "1": 206, + "2": 181, + "3": 240, + "4": 94, + "5": 219, + "6": 114, + "7": 2, + "8": 107, + "9": 207, + "10": 152, + "11": 28, + "12": 148, + "13": 241, + "14": 2, + "15": 148, + "16": 200, + "17": 212, + "18": 95, + "19": 77, + "20": 1, + "21": 186, + "22": 179, + "23": 162, + "24": 32, + "25": 216, + "26": 223, + "27": 22, + "28": 76, + "29": 61, + "30": 94, + "31": 203 + }, + "index": 260, + "account": "0xE94dc0038fAD3Bee81cD5eb54E02407CdDAD9a60", + "proof": [ + "0xf66a64c6b93269cbe6648a25111eab894edecc8bfc7146be1b80462982dc76b9", + "0x01840fef395955c1ffab0190e185a1e4e00c39d5bad2d46fc0f0f6ed0c7bf367", + "0x7a64198bc497a4465cfe60609f06b28b93220df36c48a504ef75feb198868689", + "0x415afb9adc1b79fc758a10c06b82fbdb020b4c15034aa142031dd8d167383ff7", + "0x4ced2037a4343c973b4f31226b11a0c4ad66f8d3ba93a58abe1ad3f52bee37f2", + "0x199289f8be72bebb34866c29cbe95e9f374c18f61de30b9671f334125971bd87", + "0xaae970f3226e259a58f4a0dda903a5f743d15d606867b7394ccdd139004c2433" + ] + }, + { + "v": 28, + "r": { + "0": 248, + "1": 202, + "2": 84, + "3": 144, + "4": 95, + "5": 244, + "6": 10, + "7": 48, + "8": 250, + "9": 40, + "10": 190, + "11": 112, + "12": 108, + "13": 140, + "14": 10, + "15": 212, + "16": 252, + "17": 127, + "18": 173, + "19": 209, + "20": 190, + "21": 3, + "22": 188, + "23": 199, + "24": 124, + "25": 35, + "26": 108, + "27": 189, + "28": 41, + "29": 141, + "30": 108, + "31": 123 + }, + "s": { + "0": 48, + "1": 173, + "2": 86, + "3": 115, + "4": 203, + "5": 18, + "6": 12, + "7": 146, + "8": 150, + "9": 252, + "10": 74, + "11": 44, + "12": 230, + "13": 237, + "14": 110, + "15": 179, + "16": 145, + "17": 190, + "18": 204, + "19": 52, + "20": 124, + "21": 81, + "22": 215, + "23": 7, + "24": 40, + "25": 76, + "26": 75, + "27": 91, + "28": 23, + "29": 26, + "30": 197, + "31": 18 + }, + "index": 290, + "account": "0x01BEA320fe842E39dFc559d2316Ac4AcB2E3c17B", + "proof": [ + "0xb06a220df5a620e5723c3c7d5dd4252da1ac29abd2b1730e1d18c12713297ce1", + "0x5782b7b385b33e5ab799e824f080cd03a092f32e89144b6022570986710f2572", + "0xc5f613829c6f188e934a1064f2d4643a50ad69d3877a30313257814ef3413dc3", + "0x67b4644bea2b3ed13a16e64bf6e0bf9cada409232106972c00d0b7070ae5acbe", + "0x75fda4b696227a082ae644377814cb58e5b22955eaba511048eb6794fbc071f3", + "0xaae970f3226e259a58f4a0dda903a5f743d15d606867b7394ccdd139004c2433" + ] + } + ], + "finalValidatorsProofRaw": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000f4000000000000000000000000000000000000000000000000000000000000011400000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000000000001b3857b94943abf55ed87faf78c9dc00e5f8480ada43cf285a9a83840345db2fde4f8e4f57cc435ead38de046020bc11727f8bec23f6ad436dbcb661808b09c964000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000005473090d3a9d7b984b31f2d36f2d004a9188796d00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000092d3fe5fcf7e9b1559b73b0055d813911a135fd0f7311e5a69899cf420c418c9f8df6a7abbefe9b2fe4e384876b71ec1eb90d23950c68b78df4e22909590d19307126a8044f997db28aaf469f8f66a8a4c09c25ab03c0b902bf02618d54d5e86e325666c5a681388f68098fa3270d9f8b05de0c3a929cf61ce2fff465db97ffa4df9973cc4b389edb18d204fb23baa094715a7f530e120a19fd643bd338f242ed8c83332339cab7a6008352495919f7102dbe1cc4d6d243682565de39b33d4899b8aefe65af72a69011a5539ab2d19e55a34db316d3b0235a2117d5b6fc42ffdef804afe61ff1c61cdcb536df0f29b62f6ca8ae121863b66c826a2ee9823f336573c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001c86095b0ac912a2ed2e7b16970aee9f5ce7efb18512e80d4076c4750f3e72bdea2b32a12e7285be4ec049df9a2d2bdab750f000e0f80cc90f8c9cb07315ef5a8f0000000000000000000000000000000000000000000000000000000000000053000000000000000000000000e11ceabdd29528affcc2f7936e0e80877ccf1e1a00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000995f466dc7f9837f333cf284f84b3ef47d968203b93571d6e67379a55239bac681f22928e92219f9cbe815f7a2baa4b71238a975a4017f36fdbe7cc736cc7787070e953d23047cbc07dc21fa318e1dd6851ccd19a5fed5976976a78236a66d6477bc44cfe90425291d8c8808375892cb895a9dd67ffd994a74bb0985b7072d98be1f4f439878975a3e8cfc749957c8b204653fd135da9b547d30269713885961303abdd191345b346cc826490fd23eb43349fab167ad091f4c48d9d2f6d70a5402586b1acf8187086c42dd317785c79d85fb281987845a982517a5925ff9c7b2bf804afe61ff1c61cdcb536df0f29b62f6ca8ae121863b66c826a2ee9823f336573c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001c400653d73c29dbae66690bf91a57e7824d9c93571e186624f2e735ba5ffab90d5baee02fe15a02f40a1f5df878bedd46fa55861b5e072c92f94cec69328ebae40000000000000000000000000000000000000000000000000000000000000076000000000000000000000000b79df9bbd3cc5a316374d40a35898657e2d8e18e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000097df725da049349c532528abe804b608d47fd20993d68053fc1b3d6042ca0002b2f3e8719554d71589ae679692ef3951fdaee3445126323eddf5edfbc78be6aa5a44761bb661fd68431ba5962280d515d2e286060fac0a5893bf5c7a7bc4309d13669134efbdc64823fbca48af53f72ffb0dccdef81c3b0d35f804893d535e8866eafa8fc9b0e67ab52141344ed25288a2bb3d158af038ea9ecc3c2ddf30f32e79c88a3c47b71bf6a0902cb29f0acc01a5e6b16f50d9030a2c6b6cc46aa3abfc82586b1acf8187086c42dd317785c79d85fb281987845a982517a5925ff9c7b2bf804afe61ff1c61cdcb536df0f29b62f6ca8ae121863b66c826a2ee9823f336573c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001be0879a1e8b9b829ad49c315c2a5fd6ee2676ada4d7adb8e3462e1843951b6935743ee89aa44a3b6b25051a7b82adc1ed19e4d292269e193d7caf707d9a5333b8000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000c66888ddebd37d715b5278a86a35d58f0d9b90f400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000908b8935325ae43169b960e19bb8d97eadf46e3e881978aff6decf2cad2edd8d4518211971ae9be734ef9576dc3a94f2e7a24cee2b67d158e6af5e6ede48b8e2b1137b81220981703e7f8fb9c13d3052513b17f8fe0dc801500ea64b25eee49fe42a0104a13de7b8090ba2326a97024c1157d88281804ce5fb85ea82abaf1eef4e05e69cbeca48f72fd3d81601b5419215fb234ba3a76467e8cd973d335c9e83ac72bd3c5ef89cc841cebd46ee834312bbb107ee0b90e729f93eb7ce924ea2d8064aaad909501e44338a8a9191abc63f8def273fb9f03108864016a17cad259dcf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001cb324da60a4789c9c63bb287edf989b4108131d295bc859d0e7316b653255d2930a00e9fb7b1beeb1dc917d06da451e2be7e1edffc13894af1e61c1accc12ac8100000000000000000000000000000000000000000000000000000000000000a300000000000000000000000066a04195acacaf002d88928b582f729e5265581500000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000090cd1ee823e290df8b9dff0067abab1eaed0749a7453852fffedbf62429be96084a77cc45d751eb4a541863939cdc472bd7179db4e9bce47aff72e11d53d824ca136d1789bce723dc057eea270cb480ec6e3308e1fdffe9d1e9fdc26b673b37f168a649c5d1d5b44417b82100e8f3a87587a7affaadd64d88e6d5af06f3878c72a907b494272792d0106ddc58923600fa00a366d0eb6bd7264a9fcea91d5585fb137973435ae824f670344e596684069be579cc265fa6f74b78a23a04ef85d88d64aaad909501e44338a8a9191abc63f8def273fb9f03108864016a17cad259dcf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001bd928f613ebc8992397dfdc3385e8e6b4de94dc5f4b92de5799aa04a59cb09a19220535333be5a78fa5e3a51d67f4870e9c486557fc201a76c16506cedd6c478600000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000085098dfb29a8a71208ffe981886a33a2c3e3f2b200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000009c90699ab2080cfb90faf611369b3270e75c46722954fb05ddc48ff4231d6bee36ba8a511b931a886b8547f75c94c89188aa817901edbcf4076d2e28c29cda4aa0268cdd4761f48b12c987142c2f89dace26b4cfea9edef0e71a934a805d157942ba6746783167c393bea28563490ded0680108da88f6fd0245e8b8e18b1004fc599a8674d32d090e93042776f9b7c43790c455091892e35deb595b5954a7471e137973435ae824f670344e596684069be579cc265fa6f74b78a23a04ef85d88d64aaad909501e44338a8a9191abc63f8def273fb9f03108864016a17cad259dcf2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001cb68fec99539f7c8337f89592c0f9dcb2bc37fcbfedd344e3d982ce254a75fb541a568e7d58cdc1dcdb36bc98df84b74453b038fbd527cbb94758c408431e4b4900000000000000000000000000000000000000000000000000000000000000dd0000000000000000000000003b5f3d19020fb26367a6a0ea611cb0e7de28de3300000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000091b1b9ace3e2c1a1785ee845eed31a37e3d9dffdd2702868b18d8ff2a5b309ea5e37762d4ee9ceac6ff6676f1cc9e062a81aa4dbcb60946f32f4d8b72c2b8cadd6861b76364d1c3170f84724667f2dab3c206b1a2b3db9a5b1ca64ba233997c5f85067ce849428405cf1b407341b9376d504e3ff593b00e4aae4f65e30a36db3ca3e540d32650f8682146d5649323edcf497d1451d505914616d409a89efff9da1bcc228cc309f83f90031fb5c788d2487eed6b8a12c98774d7a9c23c0cee17c6dbf5e78cdca685e455240593bc327f715dbb1552bdcd7e5f821dc6cc41e2cfb0f2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001cd4d4e5c14a33054c5b8abe9c88953aef2c86567a87fe42526404a4887a4d5db146049cacf61c5fdc42dd2ae0cdf26456be95b2daa982b65fea36991dc5eb9ef700000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000083694089d1e2fbd01c090a3198c64a9153d2f8fa00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000099fe76ba617982f9986fc59e8521171ebe81e0c7491d91521a0fe9a0b635af8a5462f5f4793463267cac15dacb74be47bddc2f19985682e9a8dae06fbdcd60293942ca9c53961d698e1d0cd11e72c60329679204ae7a8357a4b557f88f767aacd638ed41e5e35db1049fe4794634692551b91f937358d0253016627fc3dbbf8a0ff0e576ff6a911efa30fd9002adcfa5d69f7e14818215b7fe0f22a1c226861618527ec55aceec37ad9c2b70e7e14ebe2c51994e496fcbedae2db5aedf4bd4a5edbf5e78cdca685e455240593bc327f715dbb1552bdcd7e5f821dc6cc41e2cfb0f2683e1db31d79f14ec5f379fa90e6044c55ee73ee1b5280e6dc22235cbb941d73c8c40d242d326ab7e07cd18bd406f4110d0df04f7168adf68e655359b8a3d0000000000000000000000000000000000000000000000000000000000000001ba8e31f87bed3b2b8dd4d72071473c9660b8cb3fd60292279c5a145a516c8e3bd73ceb5f05edb72026bcf981c94f10294c8d45f4d01bab3a220d8df164c3d5ecb0000000000000000000000000000000000000000000000000000000000000104000000000000000000000000e94dc0038fad3bee81cd5eb54e02407cddad9a6000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000007f66a64c6b93269cbe6648a25111eab894edecc8bfc7146be1b80462982dc76b901840fef395955c1ffab0190e185a1e4e00c39d5bad2d46fc0f0f6ed0c7bf3677a64198bc497a4465cfe60609f06b28b93220df36c48a504ef75feb198868689415afb9adc1b79fc758a10c06b82fbdb020b4c15034aa142031dd8d167383ff74ced2037a4343c973b4f31226b11a0c4ad66f8d3ba93a58abe1ad3f52bee37f2199289f8be72bebb34866c29cbe95e9f374c18f61de30b9671f334125971bd87aae970f3226e259a58f4a0dda903a5f743d15d606867b7394ccdd139004c2433000000000000000000000000000000000000000000000000000000000000001cf8ca54905ff40a30fa28be706c8c0ad4fc7fadd1be03bcc77c236cbd298d6c7b30ad5673cb120c9296fc4a2ce6ed6eb391becc347c51d707284c4b5b171ac512000000000000000000000000000000000000000000000000000000000000012200000000000000000000000001bea320fe842e39dfc559d2316ac4acb2e3c17b00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000006b06a220df5a620e5723c3c7d5dd4252da1ac29abd2b1730e1d18c12713297ce15782b7b385b33e5ab799e824f080cd03a092f32e89144b6022570986710f2572c5f613829c6f188e934a1064f2d4643a50ad69d3877a30313257814ef3413dc367b4644bea2b3ed13a16e64bf6e0bf9cada409232106972c00d0b7070ae5acbe75fda4b696227a082ae644377814cb58e5b22955eaba511048eb6794fbc071f3aae970f3226e259a58f4a0dda903a5f743d15d606867b7394ccdd139004c2433" +} \ No newline at end of file diff --git a/contracts/test/data/beefy-validator-set.json b/contracts/test/data/beefy-validator-set.json new file mode 100644 index 0000000000000..ee6e82d12054f --- /dev/null +++ b/contracts/test/data/beefy-validator-set.json @@ -0,0 +1,308 @@ +{ + "validatorSetSize": 300, + "participants": [ + 0, + 1, + 3, + 4, + 6, + 7, + 9, + 10, + 12, + 13, + 14, + 15, + 16, + 20, + 22, + 23, + 25, + 27, + 28, + 29, + 30, + 31, + 33, + 34, + 35, + 36, + 39, + 40, + 45, + 46, + 48, + 49, + 51, + 52, + 54, + 55, + 57, + 58, + 61, + 63, + 64, + 65, + 67, + 69, + 70, + 71, + 72, + 73, + 75, + 82, + 83, + 85, + 86, + 87, + 90, + 91, + 92, + 93, + 94, + 95, + 97, + 99, + 100, + 101, + 102, + 103, + 104, + 107, + 108, + 109, + 112, + 113, + 114, + 115, + 117, + 118, + 119, + 121, + 123, + 124, + 126, + 131, + 132, + 136, + 137, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 153, + 154, + 155, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 168, + 170, + 171, + 172, + 173, + 174, + 175, + 177, + 180, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 195, + 197, + 198, + 202, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 214, + 215, + 219, + 220, + 221, + 223, + 224, + 225, + 227, + 228, + 231, + 233, + 234, + 236, + 237, + 239, + 240, + 241, + 243, + 244, + 245, + 246, + 247, + 248, + 251, + 252, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 265, + 267, + 269, + 273, + 274, + 275, + 277, + 278, + 279, + 282, + 283, + 285, + 286, + 288, + 289, + 290, + 292, + 293, + 294, + 295, + 296, + 297, + 298 + ], + "absentees": [ + 2, + 5, + 8, + 11, + 17, + 18, + 19, + 21, + 24, + 26, + 32, + 37, + 38, + 41, + 42, + 43, + 44, + 47, + 50, + 53, + 56, + 59, + 60, + 62, + 66, + 68, + 74, + 76, + 77, + 78, + 79, + 80, + 81, + 84, + 88, + 89, + 96, + 98, + 105, + 106, + 110, + 111, + 116, + 120, + 122, + 125, + 127, + 128, + 129, + 130, + 133, + 134, + 135, + 138, + 152, + 156, + 167, + 169, + 176, + 178, + 179, + 181, + 194, + 196, + 199, + 200, + 201, + 203, + 204, + 213, + 216, + 217, + 218, + 222, + 226, + 229, + 230, + 232, + 235, + 238, + 242, + 249, + 250, + 253, + 262, + 263, + 264, + 266, + 268, + 270, + 271, + 272, + 276, + 280, + 281, + 284, + 287, + 291, + 299 + ], + "validatorRoot": "0x9e1c83813ce2c712d2753f9e3b4864e586bc34104fe2d9c40b87778977dba3b6" +} \ No newline at end of file diff --git a/core/packages/contracts/test/archive/libs/data/mmr-fixture-data-15-leaves.json b/contracts/test/data/mmr-fixture-data-15-leaves.json similarity index 100% rename from core/packages/contracts/test/archive/libs/data/mmr-fixture-data-15-leaves.json rename to contracts/test/data/mmr-fixture-data-15-leaves.json diff --git a/core/packages/contracts/test/mocks/BeefyClientMock.sol b/contracts/test/mocks/BeefyClientMock.sol similarity index 57% rename from core/packages/contracts/test/mocks/BeefyClientMock.sol rename to contracts/test/mocks/BeefyClientMock.sol index c0f83d1bc54d0..392e2696c3340 100644 --- a/core/packages/contracts/test/mocks/BeefyClientMock.sol +++ b/contracts/test/mocks/BeefyClientMock.sol @@ -1,11 +1,17 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; -import "../../src/BeefyClient.sol"; +import {BeefyClient} from "../../src/BeefyClient.sol"; contract BeefyClientMock is BeefyClient { constructor(uint256 randaoCommitDelay, uint256 randaoCommitExpiration) - BeefyClient(randaoCommitDelay, randaoCommitExpiration) + BeefyClient( + randaoCommitDelay, + randaoCommitExpiration, + 0, + BeefyClient.ValidatorSet(0, 0, 0x0), + BeefyClient.ValidatorSet(0, 0, 0x0) + ) {} function encodeCommitment_public(Commitment calldata commitment) external pure returns (bytes memory) { @@ -16,6 +22,14 @@ contract BeefyClientMock is BeefyClient { return minimumSignatureThreshold(validatorSetLen); } + function setTicketValidatorSetLen(bytes32 commitmentHash, uint32 validatorSetLen) external { + tickets[createTicketID(msg.sender, commitmentHash)].validatorSetLen = validatorSetLen; + } + + function setLatestBeefyBlock(uint32 _latestBeefyBlock) external { + latestBeefyBlock = _latestBeefyBlock; + } + function initialize_public( uint64 _initialBeefyBlock, ValidatorSet calldata _initialValidatorSet, diff --git a/contracts/test/mocks/GatewayMock.sol b/contracts/test/mocks/GatewayMock.sol new file mode 100644 index 0000000000000..54fd3aec2a839 --- /dev/null +++ b/contracts/test/mocks/GatewayMock.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Gateway} from "../../src/Gateway.sol"; +import {ParaID, OperatingMode} from "../../src/Types.sol"; +import {CoreStorage} from "../../src/storage/CoreStorage.sol"; + +contract GatewayMock is Gateway { + constructor( + address beefyClient, + address agentExecutor, + uint256 dispatchGas, + ParaID bridgeHubParaID, + bytes32 bridgeHubHubAgentID, + ParaID assetHubParaID, + bytes32 assetHubHubAgentID, + bytes2 createTokenCallID + ) + Gateway( + beefyClient, + agentExecutor, + dispatchGas, + bridgeHubParaID, + bridgeHubHubAgentID, + assetHubParaID, + assetHubHubAgentID, + createTokenCallID + ) + {} + + function agentExecutePublic(bytes calldata params) external { + this.agentExecute(params); + } + + function createAgentPublic(bytes calldata params) external { + this.createAgent(params); + } + + function upgradePublic(bytes calldata params) external { + this.upgrade(params); + } + + function createChannelPublic(bytes calldata params) external { + this.createChannel(params); + } + + function updateChannelPublic(bytes calldata params) external { + this.updateChannel(params); + } + + function setOperatingModePublic(bytes calldata params) external { + this.setOperatingMode(params); + } + + function transferNativeFromAgentPublic(bytes calldata params) external { + this.transferNativeFromAgent(params); + } +} + +library AdditionalStorage { + struct Layout { + uint256 value; + } + + bytes32 internal constant SLOT = keccak256("org.snowbridge.storage.additionalStorage"); + + function layout() internal pure returns (Layout storage sp) { + bytes32 slot = SLOT; + assembly { + sp.slot := slot + } + } +} + +// Used to test upgrades. +contract GatewayV2 { + // Reinitialize gateway with some additional storage fields + function initialize(bytes memory params) external { + AdditionalStorage.Layout storage $ = AdditionalStorage.layout(); + + uint256 value = abi.decode(params, (uint256)); + + if (value == 666) { + revert("initialize failed"); + } + + $.value = value; + } + + function getValue() external view returns (uint256) { + return AdditionalStorage.layout().value; + } +} diff --git a/core/packages/contracts/test/mocks/MMRProofWrapper.sol b/contracts/test/mocks/MMRProofWrapper.sol similarity index 79% rename from core/packages/contracts/test/mocks/MMRProofWrapper.sol rename to contracts/test/mocks/MMRProofWrapper.sol index 4cefda3cb563c..d6d9c6fe93cf3 100644 --- a/core/packages/contracts/test/mocks/MMRProofWrapper.sol +++ b/contracts/test/mocks/MMRProofWrapper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; -import "../../src/utils/MMRProof.sol"; +import {MMRProof} from "../../src/utils/MMRProof.sol"; contract MMRProofWrapper { function verifyLeafProof(bytes32 root, bytes32 leafHash, bytes32[] calldata proof, uint256 proofOrder) diff --git a/contracts/test/mocks/VerificationWrapper.sol b/contracts/test/mocks/VerificationWrapper.sol new file mode 100644 index 0000000000000..d08b9426c6e90 --- /dev/null +++ b/contracts/test/mocks/VerificationWrapper.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +import {Verification} from "../../src/Verification.sol"; + +contract VerificationWrapper { + function createParachainHeaderMerkleLeaf(bytes4 encodedParachainID, Verification.ParachainHeader calldata header) + external + pure + returns (bytes32) + { + return Verification.createParachainHeaderMerkleLeaf(encodedParachainID, header); + } + + function isCommitmentInHeaderDigest(bytes32 commitment, Verification.ParachainHeader calldata header) + external + pure + returns (bool) + { + return Verification.isCommitmentInHeaderDigest(commitment, header); + } +} diff --git a/core/package.json b/core/package.json deleted file mode 100644 index 2042bdf2d88da..0000000000000 --- a/core/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@snowbridge/core", - "private": true, - "engines": { - "node": "v18.16.1", - "pnpm": "8.6.6" - }, - "scripts": { - "preinstall": "npx only-allow pnpm", - "postinstall": "./init.sh", - "build": "turbo run build --filter '!./packages/contracts/lib/*'", - "test": "turbo run test --filter '!./packages/contracts/lib/*'", - "lint": "turbo run lint --filter '!./packages/contracts/lib/*'", - "format": "turbo run format --filter '!./packages/contracts/lib/*'", - "size": "turbo run size --filter '!./packages/contracts/lib/*'", - "coverage": "turbo run coverage --filter '!./packages/contracts/lib/*'", - "remixd": "./node_modules/.bin/remixd" - }, - "devDependencies": { - "@remix-project/remixd": "^0.6.14", - "husky": "^8.0.3", - "turbo": "^1.9.4" - } -} diff --git a/core/packages/contracts/.gas-snapshot b/core/packages/contracts/.gas-snapshot deleted file mode 100644 index 5054626955fb3..0000000000000 --- a/core/packages/contracts/.gas-snapshot +++ /dev/null @@ -1,44 +0,0 @@ -BeefyClientTest:testScaleEncodeCommit() (gas: 32228) -BeefyClientTest:testSubmit() (gas: 640426) -BeefyClientTest:testSubmitFailForPrevRandaoCapturedMoreThanOnce() (gas: 269498) -BeefyClientTest:testSubmitFailForPrevRandaoTooEarlyOrTooLate() (gas: 210184) -BeefyClientTest:testSubmitFailInvalidSignature() (gas: 581588) -BeefyClientTest:testSubmitFailValidatorNotInBitfield() (gas: 568657) -BeefyClientTest:testSubmitFailWithInvalidBitfield() (gas: 559304) -BeefyClientTest:testSubmitFailWithStaleCommitment() (gas: 757824) -BeefyClientTest:testSubmitFailWithoutPrevRandao() (gas: 535343) -BeefyClientTest:testSubmitWithHandover() (gas: 668392) -BeefyClientTest:testSubmitWithHandoverFailStaleCommitment() (gas: 781735) -BeefyClientTest:testSubmitWithHandoverFailWithoutPrevRandao() (gas: 559560) -InboundQueueTest:testSubmit() (gas: 117979) -InboundQueueTest:testSubmitShouldFailInsufficientBalance() (gas: 92436) -InboundQueueTest:testSubmitShouldFailInvalidNonce() (gas: 66955) -InboundQueueTest:testSubmitShouldFailInvalidProof() (gas: 62637) -InboundQueueTest:testSubmitShouldNotFailOnHandlerFailure() (gas: 142351) -InboundQueueTest:testSubmitShouldNotFailOnHandlerOOG() (gas: 641523) -NativeTokensTest:testCreateFailOnBadFeePayment() (gas: 11593) -NativeTokensTest:testCreateFailOnBadToken() (gas: 19174) -NativeTokensTest:testCreateSuccessful() (gas: 79603) -NativeTokensTest:testHandleRevertsUnknownOrigin() (gas: 12280) -NativeTokensTest:testHandleRevertsUnknownSender() (gas: 44241) -NativeTokensTest:testHandleUnlockMessageSuccessful() (gas: 154612) -NativeTokensTest:testLockRevertsZeroAmount() (gas: 11361) -NativeTokensTest:testLockSuccessful() (gas: 161012) -OutboundQueueTest:testSubmit() (gas: 82052) -OutboundQueueTest:testSubmitFailFeePaymentTooLow() (gas: 30057) -ParachainClientTest:testCreateParachainHeaderMerkleFailInvalidHeader() (gas: 12690) -ParachainClientTest:testCreateParachainHeaderMerkleLeaf() (gas: 23474) -ParachainClientTest:testIsCommitmentInHeaderDigest() (gas: 23454) -ScaleCodecTest:testEncodeU128() (gas: 193) -ScaleCodecTest:testEncodeU16() (gas: 414) -ScaleCodecTest:testEncodeU256() (gas: 453) -ScaleCodecTest:testEncodeU32() (gas: 171) -ScaleCodecTest:testEncodeU64() (gas: 281) -TokenVaultTest:testDepositSuccessful() (gas: 106091) -TokenVaultTest:testInsufficientBalance() (gas: 17425) -TokenVaultTest:testNonOwnerCannotWithdraw() (gas: 44613) -TokenVaultTest:testTokenTransferFailedInsufficientAllowance() (gas: 69957) -TokenVaultTest:testWithdrawSuccessful() (gas: 121381) -UpgradeProxyTest:testUpgrade() (gas: 35658) -UpgradeProxyTest:testUpgradeFail() (gas: 20802) -UpgradeProxyTest:testUpgradeFailBadOrigin() (gas: 11326) diff --git a/core/packages/contracts/.mocharc.json b/core/packages/contracts/.mocharc.json deleted file mode 100644 index 353a082c7599f..0000000000000 --- a/core/packages/contracts/.mocharc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "require": "hardhat/register", - "timeout": 40000, - "_": ["test/**/*.ts"] -} - diff --git a/core/packages/contracts/.solcover.js b/core/packages/contracts/.solcover.js deleted file mode 100644 index 491fc324c8321..0000000000000 --- a/core/packages/contracts/.solcover.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - skipFiles: ['MaliciousDOTApp.sol', 'test'], -}; diff --git a/core/packages/contracts/.solhint.json b/core/packages/contracts/.solhint.json deleted file mode 100644 index 66cd1309c29c6..0000000000000 --- a/core/packages/contracts/.solhint.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "solhint:recommended", - "rules": { - "compiler-version": ["error", "0.8.20"], - "func-visibility": ["warn", {"ignoreConstructors":true}], - "not-rely-on-time": "off", - "avoid-low-level-calls": "off", - "no-inline-assembly": "off" - } -} diff --git a/core/packages/contracts/.solhintignore b/core/packages/contracts/.solhintignore deleted file mode 100644 index f6e1d24ea78b0..0000000000000 --- a/core/packages/contracts/.solhintignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules/ -src/ -test/ -dist/ -artifacts/ -lib/ diff --git a/core/packages/contracts/README.md b/core/packages/contracts/README.md deleted file mode 100644 index 6d477bf11de26..0000000000000 --- a/core/packages/contracts/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Ethereum Contracts - -Solidity smart contracts and tests for snowbridge. - -## Development - -Requirements: -* direnv: https://direnv.net/docs/installation.html - -Create an `.envrc` file using [.envrc.template](.envrc.template) as a template. Note that deploying to goerli network requires setting the INFURA_PROJECT_ID and ROPSTEN_PRIVATE_KEY environment variables. - -Example: - -```bash -cp .envrc-example .envrc -direnv allow -``` - -## Testing - -Run tests: - -```bash -pnpm test -``` - -Set `REPORT_GAS=1` when running tests to generate a gas report. - -## Test Fixtures - -Some of the unit tests require fixture data generated by a live deployment. For this purpose, we use logging artifacts from the offchain relayers in the [E2E](../test) stack. - -To generate logging artifacts, run the following E2E tests: - -```bash -cd ../test -pnpm test:integration --grep 'should transfer DOT from Substrate to Ethereum \(basic channel\)' -pnpm test:integration --grep 'should transfer ETH from Ethereum to Substrate \(basic channel\)' -``` - -### BEEFY commitments - -BEEFY commitment & proofs extracted from `../test/beefy-relay.log` and copied into: -* `test/beefy/data/beefy-commitment.json` - -To update `basic-commitment.json`: -1. Search for `Sent SubmitFinal transaction` in `beefy-relay.log` -2. Copy into `test/beefy/data/beefy-commitment.json` - -### Message bundles - -Message bundles are extracted from `../test/parachain-relay.log` and copied into `test/channels/data/basic-commitment.json`. - -To update `basic-commitment.json`: -1. Search for `Sent transaction InboundQueue.submit` in `parachain-relay.log` -2. Copy the necessary fields into `test/channels/data/basic-commitment.json` diff --git a/core/packages/contracts/lib/forge-std b/core/packages/contracts/lib/forge-std deleted file mode 160000 index 9b49a72cfdb36..0000000000000 --- a/core/packages/contracts/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9b49a72cfdb36bcf195eb863f868f01a6d6d3186 diff --git a/core/packages/contracts/lib/openzeppelin-contracts b/core/packages/contracts/lib/openzeppelin-contracts deleted file mode 160000 index d00acef405980..0000000000000 --- a/core/packages/contracts/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d00acef4059807535af0bd0dd0ddf619747a044b diff --git a/core/packages/contracts/package.json b/core/packages/contracts/package.json deleted file mode 100644 index d63e5090f635d..0000000000000 --- a/core/packages/contracts/package.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "name": "@snowbridge/contracts", - "version": "1.0.0", - "description": "Snowbridge smart contracts", - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/Snowfork/snowbridge.git", - "directory": "core/packages/contracts" - }, - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "build": "pnpm build:sol && pnpm build:types", - "build:sol": "forge build", - "build:types": "typechain --target ethers-v5 'out/**/!(*.t|test).sol/!(*.abi).json' --out-dir types", - "lint": "pnpm lint:solhint", - "lint:solhint": "solhint 'src/**/*.sol'", - "format": "forge fmt", - "size": "forge build --sizes", - "test": "pnpm test:foundry", - "test:foundry": "pnpm build && forge test -vvv", - "deploy:foundry": "forge script --rpc-url http://127.0.0.1:8545/ scripts/Deploy.sol:DeployScript --broadcast -vvvv" - }, - "devDependencies": { - "@babel/core": "^7.11.6", - "@ethereum-waffle/mock-contract": "^3.4.4", - "@ethersproject/abi": "^5.0.0", - "@ethersproject/hdnode": "^5.7.0", - "@iarna/toml": "^2.2.5", - "@polkadot/api": "10.7.1", - "@polkadot/types": "10.7.1", - "@typechain/ethers-v5": "^10.1.1", - "@types/keccak": "^3.0.1", - "@types/lodash": "^4.14.186", - "@types/mocha": "^10.0.0", - "@types/node": "^18.13.0", - "@types/secp256k1": "^4.0.3", - "@types/seedrandom": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", - "bitfield": "^4.1.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.1", - "chai-bignumber": "^3.0.0", - "esbuild": "^0.17.4", - "eslint": "^8.26.0", - "eslint-config-prettier": "^8.5.0", - "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^7.0.10", - "find-config": "^1.0.0", - "keccak": "^3.0.2", - "lodash": "^4.17.21", - "merkletreejs": "^0.2.18", - "mocha": "^10.1.0", - "prettier": "^2.6.2", - "prettier-plugin-solidity": "^1.0.0", - "rlp": "^2.2.6", - "secp256k1": "^4.0.2", - "seedrandom": "^3.0.5", - "solc": "^0.7.6", - "solhint": "^3.3.7", - "solidity-docgen": "^0.5.10", - "temp": "^0.9.1", - "ts-node": "^10.9.1", - "tsconfig-paths": "^4.1.0", - "typechain": "^8.1.1", - "typescript": "^4.3.2", - "unique-filename": "^1.1.1" - }, - "dependencies": { - "@ethersproject/bytes": "^5.0.0", - "@ethersproject/providers": "^5.4.7", - "@ethersproject/units": "^5.4.7", - "ethers": "^5.7.2" - } -} diff --git a/core/packages/contracts/scripts/ffiWrapper.ts b/core/packages/contracts/scripts/ffiWrapper.ts deleted file mode 100755 index 8497f558b1ef0..0000000000000 --- a/core/packages/contracts/scripts/ffiWrapper.ts +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env node -import { ValidatorSet, createRandomSubset, readSetBits } from "./helpers" -import { BigNumber, ethers } from "ethers" -import fs from "fs" -import type { BeefyClient } from "../types/BeefyClient" -import { accounts } from "./wallets" - -const encoder = new ethers.utils.AbiCoder() -const command = process.argv[2] -const fixtureData = JSON.parse(fs.readFileSync("test/data/beefy-commitment.json", "utf8")) -const validatorSetID = fixtureData.params.id -const validatorSetSize = process.env["FixedSet"] == "true" ? accounts.length : 300 -const commitHash = fixtureData.commitmentHash -const blockNumber = fixtureData.params.commitment.blockNumber -const mmrLeafProofs = fixtureData.params.leafProof -const mmrRoot = fixtureData.params.commitment.payload[0].data -const mmrLeaf: BeefyClient.MMRLeafStruct = fixtureData.params.leaf -const leafProofOrder = fixtureData.params.leafProofOrder - -const absentSubsetSize = Math.floor((validatorSetSize - 1) / 3) -const subsetSize = validatorSetSize - absentSubsetSize -const subset = createRandomSubset(validatorSetSize, subsetSize) -const absentSubset = createRandomSubset(validatorSetSize, absentSubsetSize) -let validatorSet: ValidatorSet - -if (command == "GenerateInitialSet") { - process.stdout.write( - `${encoder.encode( - ["uint32", "uint32", "uint32", "uint256[]", "uint256[]", "bytes32", "bytes32"], - [blockNumber, validatorSetID, validatorSetSize, subset, absentSubset, commitHash, mmrRoot] - )}` - ) -} else if (command == "GenerateProofs") { - if (process.env["FixedSet"] == "true") { - validatorSet = new ValidatorSet( - validatorSetID, - validatorSetSize, - accounts.map((account) => account.privateKey) - ) - } else { - validatorSet = new ValidatorSet(validatorSetID, validatorSetSize) - } - const finalBitfieldLength = parseInt(process.argv[3]) - let finalBitfield: BigNumber[] = [] - for (let i = 0; i < finalBitfieldLength; i++) { - finalBitfield.push(ethers.BigNumber.from(process.argv[4 + i])) - } - const validatorFinalProofs: BeefyClient.ValidatorProofStruct[] = readSetBits(finalBitfield).map( - (i) => validatorSet.createSignatureProof(i, commitHash) - ) - process.stdout.write( - `${encoder.encode( - [ - "bytes32", - "tuple(uint8 v, bytes32 r, bytes32 s, uint256 index,address account,bytes32[] proof)[]", - "bytes32[]", - "tuple(uint8 version,uint32 parentNumber,bytes32 parentHash,uint64 nextAuthoritySetID,uint32 nextAuthoritySetLen,bytes32 nextAuthoritySetRoot,bytes32 parachainHeadsRoot)", - "uint256", - ], - [validatorSet.root, validatorFinalProofs, mmrLeafProofs, mmrLeaf, leafProofOrder] - )}` - ) -} diff --git a/core/packages/contracts/scripts/generateContractInfo.js b/core/packages/contracts/scripts/generateContractInfo.js deleted file mode 100644 index e6bf1cf24339e..0000000000000 --- a/core/packages/contracts/scripts/generateContractInfo.js +++ /dev/null @@ -1,42 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const NetworkId = process.env.ETH_NETWORK_ID || 15; -const DeployInfoFile = `./broadcast/DeployScript.sol/${NetworkId}/run-latest.json`; -const BuildInfoDir = "./out"; -const DestFile = - process.argv.length >= 3 ? process.argv[2] : (process.env["output_dir"] + "/contracts.json"); - -const run = async () => { - let contracts = {}; - const deploymentInfo = JSON.parse(fs.readFileSync(DeployInfoFile, "utf8")); - for (let transaction of deploymentInfo.transactions) { - if (transaction.transactionType === "CREATE") { - let contractName = transaction.contractName; - if (contractName) { - let contractInfo = { address: transaction.contractAddress }; - let contractBuildingInfo = JSON.parse( - fs.readFileSync( - path.join( - BuildInfoDir, - contractName + ".sol", - contractName + ".json" - ), - "utf8" - ) - ); - contractInfo.abi = contractBuildingInfo.abi; - contracts[contractName] = contractInfo; - } - } - } - fs.writeFileSync(DestFile, JSON.stringify({ contracts }, null, 2), "utf8"); -}; - -run() - .then(() => { - console.log("Contract File generated successfully"); - process.exit(0); - }) - .catch((err) => { - console.error(err); - }); diff --git a/core/packages/contracts/src/Auth.sol b/core/packages/contracts/src/Auth.sol deleted file mode 100644 index 44d585adc1b66..0000000000000 --- a/core/packages/contracts/src/Auth.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; - -contract Auth is AccessControl { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - - constructor() { - _grantRole(ADMIN_ROLE, msg.sender); - _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); - } -} diff --git a/core/packages/contracts/src/DeployScript.sol b/core/packages/contracts/src/DeployScript.sol deleted file mode 100644 index 37e0db9b8d370..0000000000000 --- a/core/packages/contracts/src/DeployScript.sol +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {WETH9} from "canonical-weth/WETH9.sol"; -import {Script} from "forge-std/Script.sol"; -import {BeefyClient} from "../src/BeefyClient.sol"; -import {ParachainClient} from "../src/ParachainClient.sol"; -import {InboundQueue} from "../src/InboundQueue.sol"; -import {IRecipient} from "../src/IRecipient.sol"; -import {OutboundQueue} from "../src/OutboundQueue.sol"; -import {NativeTokens} from "../src/NativeTokens.sol"; -import {TokenVault} from "../src/TokenVault.sol"; -import {Vault} from "../src/Vault.sol"; -import {UpgradeProxy} from "../src/UpgradeProxy.sol"; -import {SovereignTreasury} from "../src/SovereignTreasury.sol"; -import {Registry} from "../src/Registry.sol"; -import {ParaID} from "../src/Types.sol"; - -contract DeployScript is Script { - Registry public registry; - Vault public vault; - BeefyClient public beefyClient; - ParachainClient public parachainClient; - InboundQueue public inboundQueue; - OutboundQueue public outboundQueue; - TokenVault public tokenVault; - NativeTokens public nativeTokens; - UpgradeProxy public upgradeProxy; - - function setUp() public {} - - function run() public { - uint256 privateKey = vm.envUint("PRIVATE_KEY"); - address deployer = vm.rememberKey(privateKey); - vm.startBroadcast(deployer); - - // Registry - registry = new Registry(); - registry.grantRole(registry.REGISTER_ROLE(), deployer); - - // Vault - vault = new Vault(); - - // SovereignTreasury - SovereignTreasury treasury = new SovereignTreasury(registry, vault); - registry.registerContract(keccak256("SovereignTreasury"), address(treasury)); - - // BeefyClient - uint256 randaoCommitDelay = vm.envUint("RANDAO_COMMIT_DELAY"); - uint256 randaoCommitExpiration = vm.envUint("RANDAO_COMMIT_EXP"); - beefyClient = new BeefyClient(randaoCommitDelay, randaoCommitExpiration); - - // ParachainClient - uint32 paraId = uint32(vm.envUint("BRIDGE_HUB_PARAID")); - parachainClient = new ParachainClient(beefyClient, paraId); - - // InboundQueue - uint256 relayerReward = vm.envUint("RELAYER_REWARD"); - inboundQueue = new InboundQueue(registry, parachainClient, vault, relayerReward); - registry.registerContract(keccak256("InboundQueue"), address(inboundQueue)); - - // OutboundQueue - uint256 relayerFee = vm.envUint("RELAYER_FEE"); - outboundQueue = new OutboundQueue(registry, vault, relayerFee); - registry.registerContract(keccak256("OutboundQueue"), address(outboundQueue)); - - // NativeTokens - tokenVault = new TokenVault(); - nativeTokens = new NativeTokens( - registry, - tokenVault, - ParaID.wrap(uint32(vm.envUint("ASSET_HUB_PARAID"))), - vm.envUint("CREATE_TOKEN_FEE"), - bytes2(vm.envBytes("CREATE_CALL_INDEX")), - bytes2(vm.envBytes("SET_METADATA_CALL_INDEX")) - ); - registry.registerContract(keccak256("NativeTokens"), address(nativeTokens)); - - // Deploy WETH for testing - new WETH9(); - - // UpgradeProxy - upgradeProxy = new UpgradeProxy(registry, ParaID.wrap(paraId)); - registry.registerContract(keccak256("UpgradeProxy"), address(upgradeProxy)); - - // Allow inbound queue to send messages to handlers - nativeTokens.grantRole(nativeTokens.SENDER_ROLE(), address(inboundQueue)); - treasury.grantRole(treasury.SENDER_ROLE(), address(inboundQueue)); - upgradeProxy.grantRole(upgradeProxy.SENDER_ROLE(), address(inboundQueue)); - - // Allow handlers to send messages to outbound queue - outboundQueue.grantRole(outboundQueue.SUBMIT_ROLE(), address(nativeTokens)); - outboundQueue.grantRole(outboundQueue.SUBMIT_ROLE(), address(treasury)); - outboundQueue.grantRole(outboundQueue.SUBMIT_ROLE(), address(upgradeProxy)); - - // Allow InboundQueue and SovereignTreasury to withdraw from vault - vault.grantRole(vault.WITHDRAW_ROLE(), address(inboundQueue)); - vault.grantRole(vault.WITHDRAW_ROLE(), address(treasury)); - - // Allow NativeTokens to use TokenVault - tokenVault.grantRole(tokenVault.WITHDRAW_ROLE(), address(nativeTokens)); - tokenVault.grantRole(tokenVault.DEPOSIT_ROLE(), address(nativeTokens)); - - // Move ownership of everything to Upgrades app - - treasury.grantRole(treasury.ADMIN_ROLE(), address(upgradeProxy)); - treasury.revokeRole(treasury.ADMIN_ROLE(), deployer); - - nativeTokens.grantRole(nativeTokens.ADMIN_ROLE(), address(upgradeProxy)); - nativeTokens.revokeRole(nativeTokens.ADMIN_ROLE(), deployer); - - vault.grantRole(vault.ADMIN_ROLE(), address(upgradeProxy)); - vault.revokeRole(vault.ADMIN_ROLE(), deployer); - - tokenVault.grantRole(tokenVault.ADMIN_ROLE(), address(upgradeProxy)); - tokenVault.revokeRole(tokenVault.ADMIN_ROLE(), deployer); - - inboundQueue.grantRole(inboundQueue.ADMIN_ROLE(), address(upgradeProxy)); - inboundQueue.revokeRole(inboundQueue.ADMIN_ROLE(), deployer); - - outboundQueue.grantRole(outboundQueue.ADMIN_ROLE(), address(upgradeProxy)); - outboundQueue.revokeRole(outboundQueue.ADMIN_ROLE(), deployer); - - registry.grantRole(outboundQueue.ADMIN_ROLE(), address(upgradeProxy)); - registry.revokeRole(outboundQueue.ADMIN_ROLE(), deployer); - - upgradeProxy.revokeRole(upgradeProxy.ADMIN_ROLE(), deployer); - - // Fund the sovereign account for the BridgeHub parachain. Used to reward relayers - // of messages originating from BridgeHub - uint256 initialDeposit = vm.envUint("BRIDGE_HUB_INITIAL_DEPOSIT"); - vault.deposit{value: initialDeposit}(ParaID.wrap(paraId)); - - vm.stopBroadcast(); - } -} diff --git a/core/packages/contracts/src/Gateway.sol b/core/packages/contracts/src/Gateway.sol deleted file mode 100644 index 86fcf16c1676a..0000000000000 --- a/core/packages/contracts/src/Gateway.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; -import {Registry} from "./Registry.sol"; -import {IOutboundQueue} from "./IOutboundQueue.sol"; -import {IRecipient} from "./IRecipient.sol"; -import {ParaID} from "./Types.sol"; -import {Auth} from "./Auth.sol"; -import {RegistryLookup} from "./RegistryLookup.sol"; - -abstract contract Gateway is Auth, RegistryLookup, IRecipient { - bytes32 public constant SENDER_ROLE = keccak256("SENDER_ROLE"); - bytes32 public constant OUTBOUND_QUEUE = keccak256("OutboundQueue"); - - /* Errors */ - - error Unauthorized(); - - constructor(Registry registry) RegistryLookup(registry) { - _setRoleAdmin(SENDER_ROLE, ADMIN_ROLE); - } - - function handle(ParaID origin, bytes calldata message) external virtual; - - function outboundQueue() internal view returns (IOutboundQueue) { - return IOutboundQueue(resolve(OUTBOUND_QUEUE)); - } - - function ensureOrigin(ParaID a, ParaID b) internal pure { - if (a != b) { - revert Unauthorized(); - } - } -} diff --git a/core/packages/contracts/src/IOutboundQueue.sol b/core/packages/contracts/src/IOutboundQueue.sol deleted file mode 100644 index cab05087a168d..0000000000000 --- a/core/packages/contracts/src/IOutboundQueue.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {ParaID} from "./Types.sol"; - -interface IOutboundQueue { - event Message(ParaID indexed dest, uint64 indexed nonce, bytes payload); - - function submit(ParaID dest, bytes calldata payload) external payable; -} diff --git a/core/packages/contracts/src/IParachainClient.sol b/core/packages/contracts/src/IParachainClient.sol deleted file mode 100644 index 50834b1fa4387..0000000000000 --- a/core/packages/contracts/src/IParachainClient.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -interface IParachainClient { - function verifyCommitment(bytes32 commitment, bytes calldata opaqueProof) external view returns (bool); -} diff --git a/core/packages/contracts/src/IRecipient.sol b/core/packages/contracts/src/IRecipient.sol deleted file mode 100644 index b1910774a2ea5..0000000000000 --- a/core/packages/contracts/src/IRecipient.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {ParaID} from "./Types.sol"; - -interface IRecipient { - function handle(ParaID origin, bytes calldata message) external; -} diff --git a/core/packages/contracts/src/InboundQueue.sol b/core/packages/contracts/src/InboundQueue.sol deleted file mode 100644 index fc7da62aa395d..0000000000000 --- a/core/packages/contracts/src/InboundQueue.sol +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {MerkleProof} from "openzeppelin/utils/cryptography/MerkleProof.sol"; -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; -import {IParachainClient, ParachainClient} from "./ParachainClient.sol"; -import {Registry} from "./Registry.sol"; -import {RegistryLookup} from "./RegistryLookup.sol"; -import {Auth} from "./Auth.sol"; -import {Vault} from "./Vault.sol"; - -import {IRecipient} from "./IRecipient.sol"; -import {ParaID} from "./Types.sol"; - -contract InboundQueue is Auth, RegistryLookup { - // Nonce for each origin - mapping(ParaID origin => uint64) public nonce; - - // Light client message verifier - IParachainClient public parachainClient; - - // Relayers are rewarded from this vault - Vault public immutable vault; - - // The relayer reward for submitting a message - uint256 public reward; - - // Relayers must provide enough gas to cover message dispatch plus a buffer - uint256 public gasToForward = 500000; - uint256 public constant GAS_BUFFER = 24000; - - // Inbound message from BridgeHub parachain - struct Message { - ParaID origin; - uint64 nonce; - bytes32 recipient; - bytes payload; - } - - enum DispatchResult { - Success, - Failure - } - - event MessageDispatched(ParaID origin, uint64 nonce, DispatchResult result); - event HandlerUpdated(uint16 id, IRecipient handler); - event ParachainClientUpdated(address parachainClient); - event VaultUpdated(address vault); - event RewardUpdated(uint256 reward); - event GasToForwardUpdated(uint256 gasToForward); - event InvalidRecipient(bytes32 recipient); - - error InvalidProof(); - error InvalidNonce(); - error NotEnoughGas(); - - constructor(Registry registry, IParachainClient _parachainClient, Vault _vault, uint256 _reward) - RegistryLookup(registry) - { - parachainClient = _parachainClient; - vault = _vault; - reward = _reward; - } - - function submit(Message calldata message, bytes32[] calldata leafProof, bytes calldata headerProof) external { - bytes32 leafHash = keccak256(abi.encode(message)); - bytes32 commitment = MerkleProof.processProof(leafProof, leafHash); - if (!parachainClient.verifyCommitment(commitment, headerProof)) { - revert InvalidProof(); - } - if (message.nonce != nonce[message.origin] + 1) { - revert InvalidNonce(); - } - - // Increment nonce for origin. - // This ensures messages are not replayed. It also ensures re-entrancy protection, - // as a re-entrant call will be detected by the nonce check above. - // - // Sources of re-entrancy: - // * The relayer which gets forwarded ETH as a reward for submission - // * XCM::Transact calls to arbitrary untrusted contracts (not in scope for initial release) - nonce[message.origin]++; - - // reward the relayer - // Should revert if there are not enough funds. In which case, the origin - // should top up the funds and have a relayer resend the message. - vault.withdraw(message.origin, payable(msg.sender), reward); - - // Ensure relayers pass enough gas for message to execute. - // Otherwise malicious relayers can break the bridge by allowing handlers to run out gas. - // Resubmission of the message by honest relayers will fail as the tracked nonce - // has already been updated. - if (gasleft() < gasToForward + GAS_BUFFER) { - revert NotEnoughGas(); - } - - address recipient = resolve(message.recipient); - DispatchResult result = DispatchResult.Success; - try IRecipient(recipient).handle{gas: gasToForward}(message.origin, message.payload) {} - catch { - result = DispatchResult.Failure; - } - - emit MessageDispatched(message.origin, message.nonce, result); - } - - function updateReward(uint256 _reward) external onlyRole(ADMIN_ROLE) { - reward = _reward; - emit RewardUpdated(_reward); - } - - function updateGasToForward(uint256 _gasToForward) external onlyRole(ADMIN_ROLE) { - gasToForward = _gasToForward; - emit GasToForwardUpdated(_gasToForward); - } -} diff --git a/core/packages/contracts/src/NativeTokens.sol b/core/packages/contracts/src/NativeTokens.sol deleted file mode 100644 index 8e08c5b0630f8..0000000000000 --- a/core/packages/contracts/src/NativeTokens.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {Ownable} from "openzeppelin/access/Ownable.sol"; -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; -import {IERC20Metadata} from "openzeppelin/token/ERC20/extensions/IERC20Metadata.sol"; - -import {TokenVault} from "./TokenVault.sol"; -import {SubstrateTypes} from "./SubstrateTypes.sol"; -import {NativeTokensTypes} from "./NativeTokensTypes.sol"; -import {IOutboundQueue} from "./OutboundQueue.sol"; -import {ParaID} from "./Types.sol"; -import {Gateway} from "./Gateway.sol"; -import {Registry} from "./Registry.sol"; - -/// @title Native Tokens -/// @dev Manages locking, unlocking ERC20 tokens in the vault. Initializes ethereum native -/// tokens on the substrate side via create. -contract NativeTokens is Gateway { - /// @dev Describes the type of message. - enum Action {Unlock} - - /// @dev Message format. - struct Message { - /// @dev The action type. - Action action; - /// @dev The message payload. - bytes payload; - } - - /// @dev Unlock payload format. - struct UnlockPayload { - /// @dev The ERC20 token to unlock. - address token; - /// @dev The destination address that will receive unlocked funds. - address recipient; - /// @dev The amount to unlock. - uint128 amount; - } - - /// @dev Emitted once the funds are locked and a message is successfully queued. - event Locked(bytes recipient, address token, uint128 amount); - - /// @dev Emitted once the funds are unlocked. - event Unlocked(address recipient, address token, uint128 amount); - - /// @dev Emitted after enqueueing a a create token message to substrate. - event Created(address token); - - /// @dev Set a new outbound channel. - event OutboundQueueUpdated(address newOutboundQueue); - - /* State */ - - // Parachain ID of AssetHub (aka Statemint) - ParaID public immutable assetHubParaID; - - TokenVault public immutable vault; - - uint256 public createTokenFee; - - /* Constants */ - - // Call index for ForeignAssets::create dispatchable on AssetHub parachain - bytes2 public immutable createCallId; - - // Call index for ForeignAssets::set_metata dispatchable AssetHub parachain - bytes2 public immutable setMetadataCallId; - - /* Errors */ - - error InvalidAmount(); - error NoFundsforCreateToken(); - - constructor( - Registry registry, - TokenVault _vault, - ParaID _assetHubParaID, - uint256 _createTokenFee, - bytes2 _createCallId, - bytes2 _setMetadataCallId - ) Gateway(registry) { - vault = _vault; - assetHubParaID = _assetHubParaID; - createTokenFee = _createTokenFee; - createCallId = _createCallId; - setMetadataCallId = _setMetadataCallId; - } - - /// @dev Locks an amount of ERC20 Tokens in the vault and enqueues a mint message. - /// Requires the allowance to be set on the ERC20 token where the spender is the vault. - /// @param token The token to lock. - /// @param recipient The recipient on the substrate side. - /// @param amount The amount to lock. - function lock(address token, ParaID dest, bytes calldata recipient, uint128 amount) external payable { - if (amount == 0) { - revert InvalidAmount(); - } - - vault.deposit(msg.sender, token, amount); - - bytes memory payload = NativeTokensTypes.Mint(address(registry), token, dest, recipient, amount); - outboundQueue().submit{value: msg.value}(assetHubParaID, payload); - - emit Locked(recipient, token, amount); - } - - /// @dev Enqueues a create native token message to substrate. - /// @param token The ERC20 token address. - function create(address token) external payable { - // to avoid spam, charge a fee for creating a new token - if (msg.value < createTokenFee) { - revert NoFundsforCreateToken(); - } - - IERC20Metadata metadata = IERC20Metadata(token); - bytes memory name = bytes(metadata.name()); - if (name.length > 32) { - name = hex""; - } - bytes memory symbol = bytes(metadata.symbol()); - if (symbol.length > 32) { - symbol = hex""; - } - uint8 decimals = metadata.decimals(); - - bytes memory payload = - NativeTokensTypes.Create(address(registry), token, name, symbol, decimals, createCallId, setMetadataCallId); - outboundQueue().submit{value: msg.value}(assetHubParaID, payload); - - emit Created(token); - } - - /// @dev Processes messages from inbound channel. - /// @param origin The multilocation of the source parachain - /// @param message The message enqueued from substrate. - function handle(ParaID origin, bytes calldata message) external override onlyRole(SENDER_ROLE) { - ensureOrigin(origin, assetHubParaID); - - Message memory decoded = abi.decode(message, (Message)); - if (decoded.action == Action.Unlock) { - UnlockPayload memory payload = abi.decode(decoded.payload, (UnlockPayload)); - vault.withdraw(payload.recipient, payload.token, payload.amount); - emit Unlocked(payload.recipient, payload.token, payload.amount); - } - } -} diff --git a/core/packages/contracts/src/NativeTokensTypes.sol b/core/packages/contracts/src/NativeTokensTypes.sol deleted file mode 100644 index a8a6a7c56e6b5..0000000000000 --- a/core/packages/contracts/src/NativeTokensTypes.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {ScaleCodec} from "./ScaleCodec.sol"; -import {SubstrateTypes} from "./SubstrateTypes.sol"; -import {ParaID} from "./Types.sol"; - -library NativeTokensTypes { - /** - * @dev SCALE-encodes `router_primitives::inbound::VersionedMessage` containing payload - * `NativeTokensMessage::Create` - */ - // solhint-disable-next-line func-name-mixedcase - function Create( - address origin, - address token, - bytes memory name, - bytes memory symbol, - uint8 decimals, - bytes2 createCallIndex, - bytes2 setMetadataCallIndex - ) internal view returns (bytes memory) { - return bytes.concat( - bytes1(0x00), - ScaleCodec.encodeU64(uint64(block.chainid)), - bytes1(0x01), - bytes1(0x00), - SubstrateTypes.H160(origin), - SubstrateTypes.H160(token), - SubstrateTypes.VecU8(name), - SubstrateTypes.VecU8(symbol), - ScaleCodec.encodeU8(decimals), - createCallIndex, - setMetadataCallIndex - ); - } - - /** - * @dev SCALE-encodes `router_primitives::inbound::VersionedMessage` containing payload - * `NativeTokensMessage::Mint` - */ - // solhint-disable-next-line func-name-mixedcase - function Mint(address origin, address token, ParaID dest, bytes memory recipient, uint128 amount) - internal - view - returns (bytes memory) - { - return bytes.concat( - bytes1(0x00), - ScaleCodec.encodeU64(uint64(block.chainid)), - bytes1(0x01), - bytes1(0x01), - SubstrateTypes.H160(origin), - SubstrateTypes.H160(token), - SubstrateTypes.OptionParaID(dest), - recipient, - ScaleCodec.encodeU128(amount) - ); - } -} diff --git a/core/packages/contracts/src/OutboundQueue.sol b/core/packages/contracts/src/OutboundQueue.sol deleted file mode 100644 index 72eca4aea23f4..0000000000000 --- a/core/packages/contracts/src/OutboundQueue.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; -import {IOutboundQueue} from "./IOutboundQueue.sol"; -import {Registry} from "./Registry.sol"; -import {Vault} from "./Vault.sol"; -import {ParaID} from "./Types.sol"; -import {Auth} from "./Auth.sol"; -import {RegistryLookup} from "./RegistryLookup.sol"; - -contract OutboundQueue is Auth, RegistryLookup, IOutboundQueue { - bytes32 public constant SUBMIT_ROLE = keccak256("SUBMIT_ROLE"); - - mapping(ParaID dest => uint64) public nonce; - - Vault public immutable vault; - uint256 public fee; - - event FeeUpdated(uint256 fee); - - error FeePaymentToLow(); - - constructor(Registry registry, Vault _vault, uint256 _fee) RegistryLookup(registry) { - _setRoleAdmin(SUBMIT_ROLE, ADMIN_ROLE); - vault = _vault; - fee = _fee; - } - - function submit(ParaID dest, bytes calldata payload) external payable onlyRole(SUBMIT_ROLE) { - if (msg.value < fee) { - revert FeePaymentToLow(); - } - nonce[dest] = nonce[dest] + 1; - vault.deposit{value: msg.value}(dest); - emit Message(dest, nonce[dest], payload); - } - - function updateFee(uint256 newFee) external onlyRole(ADMIN_ROLE) { - fee = newFee; - emit FeeUpdated(fee); - } -} diff --git a/core/packages/contracts/src/ParachainClient.sol b/core/packages/contracts/src/ParachainClient.sol deleted file mode 100644 index e07002b50ecf1..0000000000000 --- a/core/packages/contracts/src/ParachainClient.sol +++ /dev/null @@ -1,240 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {MerkleProof} from "./utils/MerkleProof.sol"; -import {BeefyClient} from "./BeefyClient.sol"; -import {IParachainClient} from "./IParachainClient.sol"; -import {ScaleCodec} from "./ScaleCodec.sol"; -import {SubstrateTypes} from "./SubstrateTypes.sol"; - -contract ParachainClient is IParachainClient { - BeefyClient public immutable beefyClient; - uint32 public immutable parachainID; - bytes4 public immutable encodedParachainID; - - struct HeadProof { - uint256 pos; - uint256 width; - bytes32[] proof; - } - - struct MMRLeafPartial { - uint8 version; - uint32 parentNumber; - bytes32 parentHash; - uint64 nextAuthoritySetID; - uint32 nextAuthoritySetLen; - bytes32 nextAuthoritySetRoot; - } - - uint256 public constant DIGEST_ITEM_PRERUNTIME = 6; - uint256 public constant DIGEST_ITEM_CONSENSUS = 4; - uint256 public constant DIGEST_ITEM_SEAL = 5; - uint256 public constant DIGEST_ITEM_OTHER = 0; - uint256 public constant DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED = 8; - - struct DigestItem { - uint256 kind; - bytes4 consensusEngineID; - bytes data; - } - - struct ParachainHeader { - bytes32 parentHash; - uint256 number; - bytes32 stateRoot; - bytes32 extrinsicsRoot; - DigestItem[] digestItems; - } - - struct Proof { - ParachainHeader header; - HeadProof headProof; - MMRLeafPartial leafPartial; - bytes32[] leafProof; - uint256 leafProofOrder; - } - - error InvalidParachainHeader(); - - constructor(BeefyClient _client, uint32 _parachainID) { - beefyClient = _client; - parachainID = _parachainID; - encodedParachainID = ScaleCodec.encodeU32(_parachainID); - } - - function verifyCommitment(bytes32 commitment, bytes calldata opaqueProof) external view virtual returns (bool) { - Proof memory proof = abi.decode(opaqueProof, (Proof)); - - if (!isCommitmentInHeaderDigest(commitment, proof.header)) { - return false; - } - // Compute the merkle leaf hash of our parachain - bytes32 parachainHeadHash = createParachainHeaderMerkleLeaf(proof.header); - - // Compute the merkle root hash of all parachain heads - if (proof.headProof.pos >= proof.headProof.width) { - return false; - } - bytes32 parachainHeadsRoot = MerkleProof.computeRoot( - parachainHeadHash, proof.headProof.pos, proof.headProof.width, proof.headProof.proof - ); - - bytes32 leafHash = createMMRLeaf(proof.leafPartial, parachainHeadsRoot); - return beefyClient.verifyMMRLeafProof(leafHash, proof.leafProof, proof.leafProofOrder); - } - - function verifyCommitmentTest(bytes32 commitment, Proof memory proof) external view returns (bytes memory) { - if (!isCommitmentInHeaderDigest(commitment, proof.header)) { - return abi.encode(0); - } - // Compute the merkle leaf hash of our parachain - bytes32 parachainHeadHash = createParachainHeaderMerkleLeaf(proof.header); - - // Compute the merkle root hash of all parachain heads - if (proof.headProof.pos >= proof.headProof.width) { - return abi.encode(1); - } - bytes32 parachainHeadsRoot = MerkleProof.computeRoot( - parachainHeadHash, proof.headProof.pos, proof.headProof.width, proof.headProof.proof - ); - - bytes32 leafHash = createMMRLeaf(proof.leafPartial, parachainHeadsRoot); - bool res = beefyClient.verifyMMRLeafProof(leafHash, proof.leafProof, proof.leafProofOrder); - - return bytes.concat( - abi.encode(2), - abi.encode(res), - commitment, - parachainHeadHash, - parachainHeadsRoot, - leafHash, - createParachainHeader(proof.header) - ); - } - - // Verify that a message commitment is in the header digest - function isCommitmentInHeaderDigest(bytes32 commitment, ParachainHeader memory header) - internal - pure - returns (bool) - { - for (uint256 i = 0; i < header.digestItems.length; i++) { - DigestItem memory item = header.digestItems[i]; - if (item.kind == DIGEST_ITEM_OTHER && item.data.length == 32 && commitment == bytes32(item.data)) { - return true; - } - } - return false; - } - - // encodes Vec - function encodeDigestItems(DigestItem[] memory digestItems) internal pure returns (bytes memory) { - // encode all digest items into a buffer - bytes memory accum = hex""; - for (uint256 i = 0; i < digestItems.length; i++) { - accum = bytes.concat(accum, encodeDigestItem(digestItems[i])); - } - // encode number of digest items, followed by encoded digest items - return bytes.concat(ScaleCodec.encodeCompactUint(digestItems.length), accum); - } - - function encodeDigestItem(DigestItem memory digestItem) internal pure returns (bytes memory) { - if (digestItem.kind == DIGEST_ITEM_PRERUNTIME) { - return bytes.concat( - bytes1(uint8(DIGEST_ITEM_PRERUNTIME)), - digestItem.consensusEngineID, - ScaleCodec.encodeCompactUint(digestItem.data.length), - digestItem.data - ); - } else if (digestItem.kind == DIGEST_ITEM_CONSENSUS) { - return bytes.concat( - bytes1(uint8(DIGEST_ITEM_CONSENSUS)), - digestItem.consensusEngineID, - ScaleCodec.encodeCompactUint(digestItem.data.length), - digestItem.data - ); - } else if (digestItem.kind == DIGEST_ITEM_SEAL) { - return bytes.concat( - bytes1(uint8(DIGEST_ITEM_SEAL)), - digestItem.consensusEngineID, - ScaleCodec.encodeCompactUint(digestItem.data.length), - digestItem.data - ); - } else if (digestItem.kind == DIGEST_ITEM_OTHER) { - return bytes.concat( - bytes1(uint8(DIGEST_ITEM_OTHER)), ScaleCodec.encodeCompactUint(digestItem.data.length), digestItem.data - ); - } else if (digestItem.kind == DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED) { - return bytes.concat(bytes1(uint8(DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED))); - } else { - revert InvalidParachainHeader(); - } - } - - // Creates a keccak hash of a SCALE-encoded parachain header - function createParachainHeaderMerkleLeaf(ParachainHeader memory header) internal view returns (bytes32) { - // Encode Parachain header - bytes memory encodedHeader = bytes.concat( - // H256 - header.parentHash, - // Compact unsigned int - ScaleCodec.encodeCompactUint(header.number), - // H256 - header.stateRoot, - // H256 - header.extrinsicsRoot, - // Vec - encodeDigestItems(header.digestItems) - ); - - // Hash of encoded parachain header merkle leaf - return keccak256( - bytes.concat( - // u32 - encodedParachainID, - // Vec - ScaleCodec.encodeCompactUint(encodedHeader.length), - encodedHeader - ) - ); - } - - function createParachainHeader(ParachainHeader memory header) internal view returns (bytes memory) { - bytes memory encodedHeader = bytes.concat( - // H256 - header.parentHash, - // Compact unsigned int - ScaleCodec.encodeCompactUint(header.number), - // H256 - header.stateRoot, - // H256 - header.extrinsicsRoot, - // Vec - ScaleCodec.encodeCompactUint(header.digestItems.length), - encodeDigestItems(header.digestItems) - ); - - return bytes.concat( - // u32 - encodedParachainID, - // length of encoded header - ScaleCodec.encodeCompactUint(encodedHeader.length), - encodedHeader - ); - } - - function createMMRLeaf(MMRLeafPartial memory leaf, bytes32 parachainHeadsRoot) internal pure returns (bytes32) { - bytes memory encodedLeaf = bytes.concat( - ScaleCodec.encodeU8(leaf.version), - ScaleCodec.encodeU32(leaf.parentNumber), - leaf.parentHash, - ScaleCodec.encodeU64(leaf.nextAuthoritySetID), - ScaleCodec.encodeU32(leaf.nextAuthoritySetLen), - leaf.nextAuthoritySetRoot, - parachainHeadsRoot - ); - return keccak256(encodedLeaf); - } -} diff --git a/core/packages/contracts/src/Registry.sol b/core/packages/contracts/src/Registry.sol deleted file mode 100644 index 7d9b08eac1887..0000000000000 --- a/core/packages/contracts/src/Registry.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; - -contract Registry is AccessControl { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - bytes32 public constant REGISTER_ROLE = keccak256("REGISTER_ROLE"); - - mapping(bytes32 contractID => address) public registry; - - constructor() { - _grantRole(ADMIN_ROLE, msg.sender); - _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); - _setRoleAdmin(REGISTER_ROLE, ADMIN_ROLE); - } - - function registerContract(bytes32 contractID, address contractAddress) external onlyRole(REGISTER_ROLE) { - registry[contractID] = contractAddress; - } - - function lookupContract(bytes32 contractID) external view returns (address) { - return registry[contractID]; - } -} diff --git a/core/packages/contracts/src/RegistryLookup.sol b/core/packages/contracts/src/RegistryLookup.sol deleted file mode 100644 index e0998eaac9704..0000000000000 --- a/core/packages/contracts/src/RegistryLookup.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {Registry} from "./Registry.sol"; - -abstract contract RegistryLookup { - Registry public immutable registry; - - error LookupError(); - - constructor(Registry _registry) { - registry = _registry; - } - - function resolve(bytes32 contractID) internal view returns (address) { - address contractAddress = registry.lookupContract(contractID); - if (contractAddress == address(0)) { - revert LookupError(); - } - return contractAddress; - } -} diff --git a/core/packages/contracts/src/SovereignTreasury.sol b/core/packages/contracts/src/SovereignTreasury.sol deleted file mode 100644 index b5bd9630af67f..0000000000000 --- a/core/packages/contracts/src/SovereignTreasury.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; -import {Vault} from "./Vault.sol"; -import {Auth} from "./Auth.sol"; -import {Gateway} from "./Gateway.sol"; -import {Registry} from "./Registry.sol"; - -import {IRecipient} from "./IRecipient.sol"; - -import {ParaID} from "./Types.sol"; - -contract SovereignTreasury is Gateway { - Vault public immutable vault; - - struct Message { - Action action; - bytes payload; - } - - enum Action - // Withdraw from sovereign account and transfer to recipient. - // Parachain teams will occasionally send this message to retrieve collected fees. - {Withdraw} - - struct WithdrawPayload { - address payable recipient; - uint256 amount; - } - - constructor(Registry registry, Vault _vault) Gateway(registry) { - _setRoleAdmin(SENDER_ROLE, ADMIN_ROLE); - vault = _vault; - } - - // Handle a message from the bridge. - function handle(ParaID origin, bytes calldata message) external override onlyRole(SENDER_ROLE) { - Message memory decoded = abi.decode(message, (Message)); - if (decoded.action == Action.Withdraw) { - WithdrawPayload memory payload = abi.decode(decoded.payload, (WithdrawPayload)); - vault.withdraw(origin, payload.recipient, payload.amount); - } - } -} diff --git a/core/packages/contracts/src/SubstrateTypes.sol b/core/packages/contracts/src/SubstrateTypes.sol deleted file mode 100644 index 520d6e373afb3..0000000000000 --- a/core/packages/contracts/src/SubstrateTypes.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import "./ScaleCodec.sol"; -import {ParaID} from "./Types.sol"; - -/** - * @title SCALE encoders for common Substrate types - */ -library SubstrateTypes { - /** - * @dev Encodes `MultiAddress::Id`: https://crates.parity.io/sp_runtime/enum.MultiAddress.html#variant.Id - * @return bytes SCALE-encoded bytes - */ - // solhint-disable-next-line func-name-mixedcase - function MultiAddressWithID(bytes32 account) internal pure returns (bytes memory) { - return bytes.concat(hex"00", account); - } - - /** - * @dev Encodes `H160`: https://crates.parity.io/sp_core/struct.H160.html - * @return bytes SCALE-encoded bytes - */ - // solhint-disable-next-line func-name-mixedcase - function H160(address account) internal pure returns (bytes memory) { - return abi.encodePacked(account); - } - - function VecU8(bytes memory input) internal pure returns (bytes memory) { - return bytes.concat(ScaleCodec.encodeCompactUint(input.length), input); - } - - /** - * @dev Encodes `Option::None`: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None - * @return bytes SCALE-encoded bytes - */ - // solhint-disable-next-line func-name-mixedcase - function None() internal pure returns (bytes memory) { - return hex"00"; - } - - // solhint-disable-next-line func-name-mixedcase - function OptionParaID(ParaID v) internal pure returns (bytes memory) { - if (v.isNone()) { - return hex"00"; - } else { - return bytes.concat(hex"01", ScaleCodec.encodeU32(ParaID.unwrap(v))); - } - } -} diff --git a/core/packages/contracts/src/TokenVault.sol b/core/packages/contracts/src/TokenVault.sol deleted file mode 100644 index 0f4ef7aecc4ac..0000000000000 --- a/core/packages/contracts/src/TokenVault.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import "openzeppelin/access/AccessControl.sol"; -import "openzeppelin/token/ERC20/IERC20.sol"; -import "openzeppelin/token/ERC20/utils/SafeERC20.sol"; - -import {Auth} from "./Auth.sol"; - -/// @title ERC20 Vault -/// @dev Holds ERC20 Tokens on behalf of ERC20App. -contract TokenVault is Auth { - using SafeERC20 for IERC20; - - /// @dev Emitted when funds are deposited. - event Deposit(address sender, address token, uint256 amount); - - /// @dev Emitted when funds are withdrawn. - event Withdraw(address recipient, address token, uint256 amount); - - /// @dev Not enough funds to transfer. - error InsufficientBalance(); - - bytes32 public constant WITHDRAW_ROLE = keccak256("WITHDRAW_ROLE"); - bytes32 public constant DEPOSIT_ROLE = keccak256("DEPOSIT_ROLE"); - - /// @dev stores the total balance of each token locked in the vault. - mapping(address token => uint128) public balance; - - constructor() { - _setRoleAdmin(WITHDRAW_ROLE, ADMIN_ROLE); - _setRoleAdmin(DEPOSIT_ROLE, ADMIN_ROLE); - } - - function deposit(address sender, address token, uint128 amount) external onlyRole(DEPOSIT_ROLE) { - balance[token] += amount; - IERC20(token).safeTransferFrom(sender, address(this), amount); - emit Deposit(sender, token, amount); - } - - function withdraw(address recipient, address token, uint128 amount) external onlyRole(WITHDRAW_ROLE) { - if (amount > balance[token]) { - revert InsufficientBalance(); - } - - balance[token] -= amount; - IERC20(token).safeTransfer(recipient, amount); - - emit Withdraw(recipient, token, amount); - } -} diff --git a/core/packages/contracts/src/Types.sol b/core/packages/contracts/src/Types.sol deleted file mode 100644 index 18e0bed2d6d5d..0000000000000 --- a/core/packages/contracts/src/Types.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -type ParaID is uint32; - -using {eq as ==, ne as !=, isNone} for ParaID global; - -function eq(ParaID a, ParaID b) pure returns (bool) { - return ParaID.unwrap(a) == ParaID.unwrap(b); -} - -function ne(ParaID a, ParaID b) pure returns (bool) { - return !eq(a, b); -} - -function isNone(ParaID a) pure returns (bool) { - return ParaID.unwrap(a) == 0; -} diff --git a/core/packages/contracts/src/UpgradeProxy.sol b/core/packages/contracts/src/UpgradeProxy.sol deleted file mode 100644 index 673aab000a86f..0000000000000 --- a/core/packages/contracts/src/UpgradeProxy.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; -import {UpgradeTask} from "./UpgradeTask.sol"; -import {ParaID} from "./Types.sol"; -import {Gateway} from "./Gateway.sol"; -import {IRecipient} from "./IRecipient.sol"; -import {Registry} from "./Registry.sol"; - -contract UpgradeProxy is Gateway { - struct Message { - Action action; - bytes payload; - } - - enum Action {Upgrade} - - struct UpgradePayload { - address task; - } - - error InvalidMessage(); - error UpgradeFailed(); - - // Parachain ID of BridgeHub - ParaID public immutable bridgeHubParaID; - - constructor(Registry registry, ParaID _bridgeHubParaID) Gateway(registry) { - bridgeHubParaID = _bridgeHubParaID; - } - - function handle(ParaID origin, bytes calldata message) external override onlyRole(SENDER_ROLE) { - ensureOrigin(origin, bridgeHubParaID); - - Message memory decoded = abi.decode(message, (Message)); - if (decoded.action != Action.Upgrade) { - revert InvalidMessage(); - } - - UpgradePayload memory payload = abi.decode(decoded.payload, (UpgradePayload)); - - (bool success,) = payload.task.delegatecall(abi.encodeCall(UpgradeTask.run, ())); - if (!success) { - revert UpgradeFailed(); - } - } -} diff --git a/core/packages/contracts/src/UpgradeTask.sol b/core/packages/contracts/src/UpgradeTask.sol deleted file mode 100644 index 414410035f9fe..0000000000000 --- a/core/packages/contracts/src/UpgradeTask.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {Gateway} from "./Gateway.sol"; -import {Registry} from "./Registry.sol"; - -abstract contract UpgradeTask is Gateway { - constructor(Registry registry) Gateway(registry) {} - function run() external virtual; -} diff --git a/core/packages/contracts/src/Vault.sol b/core/packages/contracts/src/Vault.sol deleted file mode 100644 index 1e00b9b2a694d..0000000000000 --- a/core/packages/contracts/src/Vault.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {Auth} from "./Auth.sol"; -import {ParaID} from "./Types.sol"; - -contract Vault is Auth { - event Deposited(ParaID indexed sovereign, uint256 amount); - event Withdrawn(ParaID indexed sovereign, address recipient, uint256 amount); - - error InsufficientBalance(); - error ZeroAmount(); - error CannotSendFunds(); - - bytes32 public constant WITHDRAW_ROLE = keccak256("WITHDRAW_ROLE"); - - // Mapping of sovereign to balance - mapping(ParaID sovereign => uint256) public balances; - - constructor() { - _setRoleAdmin(WITHDRAW_ROLE, ADMIN_ROLE); - } - - receive() external payable { - revert("Must use deposit function"); - } - - function deposit(ParaID sovereign) external payable { - balances[sovereign] += msg.value; - emit Deposited(sovereign, msg.value); - } - - function withdraw(ParaID sovereign, address payable recipient, uint256 amount) external onlyRole(WITHDRAW_ROLE) { - if (amount == 0) { - revert ZeroAmount(); - } - - if (balances[sovereign] < amount) { - revert InsufficientBalance(); - } - - balances[sovereign] -= amount; - - (bool success,) = recipient.call{value: amount}(""); - if (!success) { - revert CannotSendFunds(); - } - - emit Withdrawn(sovereign, recipient, amount); - } -} diff --git a/core/packages/contracts/src/utils/Bytes.sol b/core/packages/contracts/src/utils/Bytes.sol deleted file mode 100644 index a7a6d77f00f7b..0000000000000 --- a/core/packages/contracts/src/utils/Bytes.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: MIT -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import "./Memory.sol"; - -library Bytes { - uint256 internal constant BYTES_HEADER_SIZE = 32; - - // Checks if two `bytes memory` variables are equal. This is done using hashing, - // which is much more gas efficient then comparing each byte individually. - // Equality means that: - // - 'self.length == other.length' - // - For 'n' in '[0, self.length)', 'self[n] == other[n]' - function equals(bytes memory self, bytes memory other) internal pure returns (bool equal) { - if (self.length != other.length) { - return false; - } - uint256 addr; - uint256 addr2; - assembly { - addr := add(self, /*BYTES_HEADER_SIZE*/ 32) - addr2 := add(other, /*BYTES_HEADER_SIZE*/ 32) - } - equal = Memory.equals(addr, addr2, self.length); - } - - // Copies a section of 'self' into a new array, starting at the provided 'startIndex'. - // Returns the new copy. - // Requires that 'startIndex <= self.length' - // The length of the substring is: 'self.length - startIndex' - function substr(bytes memory self, uint256 startIndex) internal pure returns (bytes memory) { - require(startIndex <= self.length); - uint256 len = self.length - startIndex; - uint256 addr = Memory.dataPtr(self); - return Memory.toBytes(addr + startIndex, len); - } - - // Copies 'len' bytes from 'self' into a new array, starting at the provided 'startIndex'. - // Returns the new copy. - // Requires that: - // - 'startIndex + len <= self.length' - // The length of the substring is: 'len' - function substr(bytes memory self, uint256 startIndex, uint256 len) internal pure returns (bytes memory) { - require(startIndex + len <= self.length); - if (len == 0) { - return ""; - } - uint256 addr = Memory.dataPtr(self); - return Memory.toBytes(addr + startIndex, len); - } - - // Combines 'self' and 'other' into a single array. - // Returns the concatenated arrays: - // [self[0], self[1], ... , self[self.length - 1], other[0], other[1], ... , other[other.length - 1]] - // The length of the new array is 'self.length + other.length' - function concat(bytes memory self, bytes memory other) internal pure returns (bytes memory) { - bytes memory ret = new bytes(self.length + other.length); - uint256 src; - uint256 srcLen; - (src, srcLen) = Memory.fromBytes(self); - uint256 src2; - uint256 src2Len; - (src2, src2Len) = Memory.fromBytes(other); - uint256 dest; - (dest,) = Memory.fromBytes(ret); - uint256 dest2 = dest + srcLen; - Memory.copy(src, dest, srcLen); - Memory.copy(src2, dest2, src2Len); - return ret; - } - - function toBytes32(bytes memory self) internal pure returns (bytes32 out) { - require(self.length >= 32, "Bytes:: toBytes32: data is to short."); - assembly { - out := mload(add(self, 32)) - } - } - - function toBytes16(bytes memory self, uint256 offset) internal pure returns (bytes16 out) { - for (uint256 i = 0; i < 16; i++) { - out |= bytes16(bytes1(self[offset + i]) & 0xFF) >> (i * 8); - } - } - - function toBytes8(bytes memory self, uint256 offset) internal pure returns (bytes8 out) { - for (uint256 i = 0; i < 8; i++) { - out |= bytes8(bytes1(self[offset + i]) & 0xFF) >> (i * 8); - } - } - - function toBytes4(bytes memory self, uint256 offset) internal pure returns (bytes4) { - bytes4 out; - - for (uint256 i = 0; i < 4; i++) { - out |= bytes4(self[offset + i] & 0xFF) >> (i * 8); - } - return out; - } - - function toBytes2(bytes memory self, uint256 offset) internal pure returns (bytes2) { - bytes2 out; - - for (uint256 i = 0; i < 2; i++) { - out |= bytes2(self[offset + i] & 0xFF) >> (i * 8); - } - return out; - } - - function removeLeadingZero(bytes memory data) internal pure returns (bytes memory) { - uint256 length = data.length; - - uint256 startIndex = 0; - for (uint256 i = 0; i < length; i++) { - if (data[i] != 0) { - startIndex = i; - break; - } - } - - return substr(data, startIndex); - } - - function removeEndingZero(bytes memory data) internal pure returns (bytes memory) { - uint256 length = data.length; - - uint256 endIndex = 0; - for (uint256 i = length - 1; i >= 0; i--) { - if (data[i] != 0) { - endIndex = i; - break; - } - } - - return substr(data, 0, endIndex + 1); - } - - function reverse(bytes memory inbytes) internal pure returns (bytes memory) { - uint256 inlength = inbytes.length; - bytes memory outbytes = new bytes(inlength); - - for (uint256 i = 0; i <= inlength - 1; i++) { - outbytes[i] = inbytes[inlength - i - 1]; - } - - return outbytes; - } -} diff --git a/core/packages/contracts/src/utils/Memory.sol b/core/packages/contracts/src/utils/Memory.sol deleted file mode 100644 index 35fb11b004ef8..0000000000000 --- a/core/packages/contracts/src/utils/Memory.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: MIT -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -library Memory { - uint256 internal constant WORD_SIZE = 32; - - // Compares the 'len' bytes starting at address 'addr' in memory with the 'len' - // bytes starting at 'addr2'. - // Returns 'true' if the bytes are the same, otherwise 'false'. - function equals(uint256 addr, uint256 addr2, uint256 len) internal pure returns (bool equal) { - assembly { - equal := eq(keccak256(addr, len), keccak256(addr2, len)) - } - } - - // Compares the 'len' bytes starting at address 'addr' in memory with the bytes stored in - // 'bts'. It is allowed to set 'len' to a lower value then 'bts.length', in which case only - // the first 'len' bytes will be compared. - // Requires that 'bts.length >= len' - - function equals(uint256 addr, uint256 len, bytes memory bts) internal pure returns (bool equal) { - require(bts.length >= len); - uint256 addr2; - assembly { - addr2 := add(bts, /*BYTES_HEADER_SIZE*/ 32) - } - return equals(addr, addr2, len); - } - - // Returns a memory pointer to the data portion of the provided bytes array. - function dataPtr(bytes memory bts) internal pure returns (uint256 addr) { - assembly { - addr := add(bts, /*BYTES_HEADER_SIZE*/ 32) - } - } - - // Creates a 'bytes memory' variable from the memory address 'addr', with the - // length 'len'. The function will allocate new memory for the bytes array, and - // the 'len bytes starting at 'addr' will be copied into that new memory. - function toBytes(uint256 addr, uint256 len) internal pure returns (bytes memory bts) { - bts = new bytes(len); - uint256 btsptr; - assembly { - btsptr := add(bts, /*BYTES_HEADER_SIZE*/ 32) - } - copy(addr, btsptr, len); - } - - // Copies 'self' into a new 'bytes memory'. - // Returns the newly created 'bytes memory' - // The returned bytes will be of length '32'. - function toBytes(bytes32 self) internal pure returns (bytes memory bts) { - bts = new bytes(32); - assembly { - mstore(add(bts, /*BYTES_HEADER_SIZE*/ 32), self) - } - } - - // Copy 'len' bytes from memory address 'src', to address 'dest'. - // This function does not check the or destination, it only copies - // the bytes. - function copy(uint256 src, uint256 dest, uint256 len) internal pure { - // Copy word-length chunks while possible - for (; len >= WORD_SIZE; len -= WORD_SIZE) { - assembly { - mstore(dest, mload(src)) - } - dest += WORD_SIZE; - src += WORD_SIZE; - } - - // Copy remaining bytes - uint256 mask = - len == 0 ? 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff : 256 ** (WORD_SIZE - len) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - } - - // This function does the same as 'dataPtr(bytes memory)', but will also return the - // length of the provided bytes array. - function fromBytes(bytes memory bts) internal pure returns (uint256 addr, uint256 len) { - len = bts.length; - assembly { - addr := add(bts, /*BYTES_HEADER_SIZE*/ 32) - } - } -} diff --git a/core/packages/contracts/src/utils/OpaqueProof.sol b/core/packages/contracts/src/utils/OpaqueProof.sol deleted file mode 100644 index 3ec5ec7f511b4..0000000000000 --- a/core/packages/contracts/src/utils/OpaqueProof.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.20; - -import {ParachainClient} from "../ParachainClient.sol"; - -// This contract is a hack which allows us to ABI-encode `ParachainClient.Proof` in the off-chain relayer. -// It is only used to generate client bindings and is never deployed. -contract OpaqueProof { - // solhint-disable-next-line no-empty-blocks - function dummy(ParachainClient.Proof memory proof) public pure {} -} diff --git a/core/packages/contracts/test/InboundQueue.t.sol b/core/packages/contracts/test/InboundQueue.t.sol deleted file mode 100644 index d8bb15aac7a69..0000000000000 --- a/core/packages/contracts/test/InboundQueue.t.sol +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import {Test} from "forge-std/Test.sol"; - -import {InboundQueue} from "../src/InboundQueue.sol"; -import {BeefyClient} from "../src/BeefyClient.sol"; -import {Vault} from "../src/Vault.sol"; -import {IParachainClient} from "../src/IParachainClient.sol"; -import {ParaID} from "../src/Types.sol"; -import {ParachainClientMock} from "./mocks/ParachainClientMock.sol"; -import {IRecipient, RecipientMock} from "./mocks/RecipientMock.sol"; -import {Registry} from "../src/Registry.sol"; - -contract InboundQueueTest is Test { - InboundQueue public channel; - RecipientMock public recipient; - - Vault public vault; - - event MessageDispatched(ParaID origin, uint64 nonce, InboundQueue.DispatchResult result); - - ParaID public constant ORIGIN = ParaID.wrap(1001); - bytes32[] public proof = [bytes32(0x2f9ee6cfdf244060dc28aa46347c5219e303fc95062dd672b4e406ca5c29764b)]; - bytes public message = bytes("message"); - bytes public parachainHeaderProof = bytes("validProof"); - - bytes32 constant RECIPIENT = keccak256("RecipientMock"); - - function setUp() public { - Registry registry = new Registry(); - registry.grantRole(registry.REGISTER_ROLE(), address(this)); - - IParachainClient parachainClient = new ParachainClientMock(BeefyClient(address(0)), 0); - recipient = new RecipientMock(); - registry.registerContract(RECIPIENT, address(recipient)); - - vault = new Vault(); - - deal(address(this), 100 ether); - - channel = new InboundQueue(registry, parachainClient, vault, 1 ether); - vault.grantRole(vault.WITHDRAW_ROLE(), address(channel)); - } - - function testSubmit() public { - vault.deposit{value: 50 ether}(ORIGIN); - - address relayer = makeAddr("alice"); - hoax(relayer, 1 ether); - - channel.submit(InboundQueue.Message(ORIGIN, 1, RECIPIENT, message), proof, parachainHeaderProof); - - assertEq(vault.balances(ORIGIN), 49 ether); - assertEq(relayer.balance, 2 ether); - } - - function testSubmitShouldFailInvalidProof() public { - vault.deposit{value: 50 ether}(ORIGIN); - - address relayer = makeAddr("alice"); - hoax(relayer, 1 ether); - - vm.expectRevert(InboundQueue.InvalidProof.selector); - channel.submit(InboundQueue.Message(ORIGIN, 1, RECIPIENT, message), proof, bytes("badProof")); - } - - function testSubmitShouldFailInvalidNonce() public { - vault.deposit{value: 50 ether}(ORIGIN); - - address relayer = makeAddr("alice"); - hoax(relayer, 1 ether); - - vm.expectRevert(InboundQueue.InvalidNonce.selector); - channel.submit(InboundQueue.Message(ORIGIN, 2, RECIPIENT, message), proof, parachainHeaderProof); - } - - // Test that submission fails if origin does not have sufficient funds to pay relayer - function testSubmitShouldFailInsufficientBalance() public { - vault.deposit{value: 0.1 ether}(ORIGIN); - - address relayer = makeAddr("alice"); - hoax(relayer, 1 ether); - - vm.expectRevert(Vault.InsufficientBalance.selector); - channel.submit(InboundQueue.Message(ORIGIN, 1, RECIPIENT, message), proof, parachainHeaderProof); - } - - function testSubmitShouldNotFailOnHandlerFailure() public { - vault.deposit{value: 50 ether}(ORIGIN); - - recipient.setShouldFail(); - vm.expectEmit(); - emit MessageDispatched(ORIGIN, 1, InboundQueue.DispatchResult.Failure); - - address relayer = makeAddr("alice"); - hoax(relayer, 1 ether); - - channel.submit(InboundQueue.Message(ORIGIN, 1, RECIPIENT, message), proof, parachainHeaderProof); - - assertEq(vault.balances(ORIGIN), 49 ether); - assertEq(relayer.balance, 2 ether); - } - - function testSubmitShouldNotFailOnHandlerOOG() public { - vault.deposit{value: 50 ether}(ORIGIN); - - recipient.setShouldConsumeAllGas(); - vm.expectEmit(); - emit MessageDispatched(ORIGIN, 1, InboundQueue.DispatchResult.Failure); - - address relayer = makeAddr("alice"); - hoax(relayer, 1 ether); - - channel.submit(InboundQueue.Message(ORIGIN, 1, RECIPIENT, message), proof, parachainHeaderProof); - - assertEq(vault.balances(ORIGIN), 49 ether); - assertEq(relayer.balance, 2 ether); - } -} diff --git a/core/packages/contracts/test/NativeTokens.t.sol b/core/packages/contracts/test/NativeTokens.t.sol deleted file mode 100644 index 9d48582e035b8..0000000000000 --- a/core/packages/contracts/test/NativeTokens.t.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import "forge-std/Test.sol"; -import "forge-std/console2.sol"; - -import {WETH9} from "canonical-weth/WETH9.sol"; - -import {IOutboundQueue} from "../src/IOutboundQueue.sol"; -import {NativeTokens} from "../src/NativeTokens.sol"; -import {TokenVault} from "../src/TokenVault.sol"; -import {ParaID} from "../src/Types.sol"; -import {Registry} from "../src/Registry.sol"; -import {Gateway} from "../src/Gateway.sol"; - -import {OutboundQueueMock} from "./mocks/OutboundQueueMock.sol"; - -contract NativeTokensTest is Test { - event Locked(bytes recipient, address token, uint128 amount); - event Unlocked(address recipient, address token, uint128 amount); - event Created(address token); - - Registry registry; - TokenVault private vault; - NativeTokens private nativeTokens; - IOutboundQueue private outboundQueue; - WETH9 private token; - address private account1; - address private account2; - - ParaID private constant ASSET_HUB = ParaID.wrap(1001); - bytes private constant recipient = "/Alice"; - - function setUp() public { - registry = new Registry(); - registry.grantRole(registry.REGISTER_ROLE(), address(this)); - - token = new WETH9(); - - outboundQueue = new OutboundQueueMock(); - registry.registerContract(keccak256("OutboundQueue"), address(outboundQueue)); - - vault = new TokenVault(); - nativeTokens = new NativeTokens(registry, vault, ASSET_HUB, 1, 0x0000, 0x0000); - vault.grantRole(vault.WITHDRAW_ROLE(), address(nativeTokens)); - vault.grantRole(vault.DEPOSIT_ROLE(), address(nativeTokens)); - - account1 = makeAddr("account1"); - account2 = address(this); - - nativeTokens.grantRole(nativeTokens.SENDER_ROLE(), address(this)); - - // create tokens for account 1 - hoax(account1); - token.deposit{value: 500}(); - - // create tokens for account 2 - token.deposit{value: 500}(); - } - - function testHandleRevertsUnknownOrigin() public { - NativeTokens.Message memory message; - vm.expectRevert(Gateway.Unauthorized.selector); - nativeTokens.handle(ParaID.wrap(4056), abi.encode(message)); - } - - function testHandleRevertsUnknownSender() public { - NativeTokens.Message memory message; - nativeTokens.revokeRole(nativeTokens.SENDER_ROLE(), address(this)); - vm.expectRevert(); - nativeTokens.handle(ASSET_HUB, abi.encode(message)); - } - - function testHandleUnlockMessageSuccessful() public { - testLockSuccessful(); - - vm.expectEmit(false, false, false, true, address(nativeTokens)); - emit Unlocked(address(account1), address(token), 50); - - NativeTokens.UnlockPayload memory payload; - payload.token = address(token); - payload.recipient = address(account1); - payload.amount = 50; - - NativeTokens.Message memory message; - message.action = NativeTokens.Action.Unlock; - message.payload = abi.encode(payload); - nativeTokens.handle(ASSET_HUB, abi.encode(message)); - - assertEq(token.balanceOf(address(account1)), 550); - assertEq(token.balanceOf(address(account2)), 450); - assertEq(token.balanceOf(address(vault)), 0); - assertEq(token.allowance(address(account2), address(vault)), 50); - assertEq(vault.balance(address(token)), 0); - } - - function testLockRevertsZeroAmount() public { - vm.expectRevert(NativeTokens.InvalidAmount.selector); - nativeTokens.lock(address(token), ParaID.wrap(0), recipient, 0); - } - - function testLockSuccessful() public { - token.approve(address(vault), 100); - - vm.recordLogs(); - - vm.expectEmit(false, false, false, true, address(nativeTokens)); - emit Locked(recipient, address(token), 50); - - nativeTokens.lock(address(token), ParaID.wrap(0), recipient, 50); - - vm.getRecordedLogs(); - - assertEq(token.balanceOf(address(account2)), 450); - assertEq(token.balanceOf(address(vault)), 50); - assertEq(token.allowance(address(account2), address(vault)), 50); - assertEq(vault.balance(address(token)), 50); - } - - function testCreateSuccessful() public { - uint256 fee = nativeTokens.createTokenFee(); - - vm.expectEmit(false, false, false, true, address(nativeTokens)); - emit Created(address(token)); - - nativeTokens.create{value: fee}(address(token)); - } - - function testCreateFailOnBadFeePayment() public { - uint256 fee = nativeTokens.createTokenFee(); - vm.expectRevert(NativeTokens.NoFundsforCreateToken.selector); - nativeTokens.create{value: fee - 1}(address(this)); - } - - function testCreateFailOnBadToken() public { - uint256 fee = nativeTokens.createTokenFee(); - vm.expectRevert(); - nativeTokens.create{value: fee}(address(this)); - } -} diff --git a/core/packages/contracts/test/OutboundQueue.t.sol b/core/packages/contracts/test/OutboundQueue.t.sol deleted file mode 100644 index 2f2413d5d47f7..0000000000000 --- a/core/packages/contracts/test/OutboundQueue.t.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import {Test} from "forge-std/Test.sol"; - -import {OutboundQueue} from "../src/OutboundQueue.sol"; -import {Vault} from "../src/Vault.sol"; -import {ParaID} from "../src/Types.sol"; -import {Registry} from "../src/Registry.sol"; - -contract OutboundQueueTest is Test { - Vault public vault; - OutboundQueue public channel; - - ParaID dest = ParaID.wrap(1001); - bytes message = bytes("message"); - - function setUp() public { - Registry registry = new Registry(); - registry.grantRole(registry.REGISTER_ROLE(), address(this)); - - vault = new Vault(); - channel = new OutboundQueue(registry, vault, 1 ether); - channel.grantRole(channel.SUBMIT_ROLE(), address(this)); - } - - function testSubmit() public { - channel.submit{value: 1 ether}(dest, message); - vault.balances(dest); - assertEq(vault.balances(dest), 1 ether); - } - - function testSubmitFailFeePaymentTooLow() public { - vm.expectRevert(OutboundQueue.FeePaymentToLow.selector); - channel.submit{value: 0.5 ether}(dest, message); - assertEq(vault.balances(dest), 0 ether); - } -} diff --git a/core/packages/contracts/test/ScaleCodec.t.sol b/core/packages/contracts/test/ScaleCodec.t.sol deleted file mode 100644 index 5254d352cff13..0000000000000 --- a/core/packages/contracts/test/ScaleCodec.t.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; - -import {ScaleCodec} from "../src/ScaleCodec.sol"; - -contract ScaleCodecTest is Test { - function testEncodeU256() public { - assertEq( - ScaleCodec.encodeU256(12063978950259949786323707366460749298097791896371638493358994162204017315152), - hex"504d8a21dd3868465c8c9f2898b7f014036935fa9a1488629b109d3d59f8ab1a" - ); - } - - function testEncodeU128() public { - assertEq(ScaleCodec.encodeU128(35452847761173902980759433963665451267), hex"036935fa9a1488629b109d3d59f8ab1a"); - } - - function testEncodeU64() public { - assertEq(ScaleCodec.encodeU64(1921902728173129883), hex"9b109d3d59f8ab1a"); - } - - function testEncodeU32() public { - assertEq(ScaleCodec.encodeU32(447477849), hex"59f8ab1a"); - } - - function testEncodeU16() public { - assertEq(ScaleCodec.encodeU16(6827), hex"ab1a"); - } -} diff --git a/core/packages/contracts/test/TokenVault.t.sol b/core/packages/contracts/test/TokenVault.t.sol deleted file mode 100644 index 83da55dcdd7d6..0000000000000 --- a/core/packages/contracts/test/TokenVault.t.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import {WETH9} from "canonical-weth/WETH9.sol"; -import "openzeppelin/token/ERC20/IERC20.sol"; - -import "../src/TokenVault.sol"; - -contract TokenVaultTest is Test { - event Deposit(address sender, address token, uint256 amount); - event Withdraw(address recipient, address token, uint256 amount); - - TokenVault vault; - WETH9 token; - address account; - - function setUp() public { - vault = new TokenVault(); - token = new WETH9(); - - account = makeAddr("statemint"); - - vault.grantRole(vault.WITHDRAW_ROLE(), address(this)); - vault.grantRole(vault.DEPOSIT_ROLE(), address(this)); - - // create tokens for statemint account - hoax(account); - token.deposit{value: 1000}(); - } - - function testInsufficientBalance() public { - vm.expectRevert(TokenVault.InsufficientBalance.selector); - vault.withdraw(address(account), address(token), 100); - } - - function testTokenTransferFailedInsufficientAllowance() public { - hoax(account); - token.approve(address(vault), 50); - - vm.expectRevert(); - vault.deposit(address(account), address(token), 100); - } - - function testDepositSuccessful() public { - hoax(account); - token.approve(address(vault), 100); - - vm.expectEmit(false, false, false, true); - emit Deposit(address(account), address(token), 50); - - vault.deposit(address(account), address(token), 50); - - assertEq(token.balanceOf(address(account)), 950); - assertEq(token.balanceOf(address(vault)), 50); - assertEq(token.allowance(address(account), address(vault)), 50); - assertEq(vault.balance(address(token)), 50); - } - - function testWithdrawSuccessful() public { - testDepositSuccessful(); - - vm.expectEmit(false, false, false, true); - emit Withdraw(address(account), address(token), 25); - - vault.withdraw(address(account), address(token), 25); - - assertEq(token.balanceOf(address(account)), 975); - assertEq(token.balanceOf(address(vault)), 25); - assertEq(vault.balance(address(token)), 25); - } - - function testNonOwnerCannotWithdraw() public { - vault.revokeRole(vault.WITHDRAW_ROLE(), address(this)); - vm.expectRevert( - "AccessControl: account 0x7fa9385be102ac3eac297483dd6233d62b3e1496 is missing role 0x5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec" - ); - vault.withdraw(address(account), address(token), 25); - } -} diff --git a/core/packages/contracts/test/UpgradeProxy.t.sol b/core/packages/contracts/test/UpgradeProxy.t.sol deleted file mode 100644 index 89e0de6f0b04f..0000000000000 --- a/core/packages/contracts/test/UpgradeProxy.t.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; - -import {Test} from "forge-std/Test.sol"; - -import {UpgradeProxy} from "../src/UpgradeProxy.sol"; -import {UpgradeTask} from "../src/UpgradeTask.sol"; -import {Vault} from "../src/Vault.sol"; -import {OutboundQueue} from "../src/OutboundQueue.sol"; -import {ParaID} from "../src/Types.sol"; -import {Registry} from "../src/Registry.sol"; -import {Gateway} from "../src/Gateway.sol"; - -import {UpgradeTaskMock, FailingUpgradeTaskMock} from "./mocks/UpgradeTaskMock.sol"; - -contract UpgradeProxyTest is Test { - UpgradeProxy public upgradeProxy; - UpgradeTask public upgradeTask; - UpgradeTask public failedUpgradeTask; - - OutboundQueue public outboundQueue; - - ParaID origin = ParaID.wrap(1001); - - function setUp() public { - Registry registry = new Registry(); - registry.grantRole(registry.REGISTER_ROLE(), address(this)); - - upgradeProxy = new UpgradeProxy(registry, origin); - registry.registerContract(keccak256("UpgradeProxy"), address(upgradeProxy)); - - outboundQueue = new OutboundQueue(registry, new Vault(), 1 ether); - registry.registerContract(keccak256("OutboundQueue"), address(outboundQueue)); - - outboundQueue.grantRole(outboundQueue.ADMIN_ROLE(), address(upgradeProxy)); - outboundQueue.revokeRole(outboundQueue.ADMIN_ROLE(), address(this)); - - upgradeProxy.grantRole(upgradeProxy.SENDER_ROLE(), address(this)); - - registry.grantRole(outboundQueue.ADMIN_ROLE(), address(upgradeProxy)); - - // create upgrade tasks - upgradeTask = new UpgradeTaskMock(registry); - failedUpgradeTask = new FailingUpgradeTaskMock(registry); - } - - function createUpgradeMessage(UpgradeTask task) internal pure returns (bytes memory) { - return abi.encode( - UpgradeProxy.Message(UpgradeProxy.Action.Upgrade, abi.encode(UpgradeProxy.UpgradePayload(address(task)))) - ); - } - - function testUpgrade() public { - bytes memory message = createUpgradeMessage(upgradeTask); - upgradeProxy.handle(origin, message); - assertEq(outboundQueue.fee(), 2 ether); - } - - function testUpgradeFailBadOrigin() public { - vm.expectRevert(Gateway.Unauthorized.selector); - upgradeProxy.handle(ParaID.wrap(3), hex"deadbeef"); - } - - function testUpgradeFail() public { - bytes memory message = createUpgradeMessage(failedUpgradeTask); - vm.expectRevert(UpgradeProxy.UpgradeFailed.selector); - upgradeProxy.handle(origin, message); - } -} diff --git a/core/packages/contracts/test/archive/libs/bitfield.test.ts b/core/packages/contracts/test/archive/libs/bitfield.test.ts deleted file mode 100644 index 5f153a9ae7201..0000000000000 --- a/core/packages/contracts/test/archive/libs/bitfield.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ethers, expect, loadFixture } from "../setup" -import { readSetBits, createRandomSubset } from "../helpers" -import { Bitfield__factory } from "../../src" - -describe("Bitfield", function () { - async function fixture() { - let [owner] = await ethers.getSigners() - let bitfieldLib = await new Bitfield__factory(owner).deploy() - return { bitfieldLib } - } - - it("creates initial bitfield correctly in simple case", async function () { - let { bitfieldLib } = await loadFixture(fixture) - - let positions = [0, 5, 8] - let bitfield = await bitfieldLib.createBitfield(positions, 9) - - expect(readSetBits(bitfield)).to.eql(positions) - }) - - it("creates initial bitfield correctly with bigger example", async function () { - let { bitfieldLib } = await loadFixture(fixture) - - let positions = createRandomSubset(200, 140) - let bitfield = await bitfieldLib.createBitfield(positions, 200) - - expect(readSetBits(bitfield)).to.eql(positions) - }) -}) diff --git a/core/packages/contracts/test/archive/libs/data/mmr-fixture-data-7-leaves.json b/core/packages/contracts/test/archive/libs/data/mmr-fixture-data-7-leaves.json deleted file mode 100644 index 60deff1f1b4c0..0000000000000 --- a/core/packages/contracts/test/archive/libs/data/mmr-fixture-data-7-leaves.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "leaves": [ - "0x11da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9", - "0xe12c22d4f162d9a012c9319233da5d3e923cc5e1029b8f90e47249c9ab256b35", - "0x7b0aa1735e5ba58d3236316c671fe4f00ed366ee72417c9ed02a53a8019e85b8", - "0x8c039ff7caa17ccebfcadc44bd9fce6a4b6699c4d03de2e3349aa1dc11193cd7", - "0x26a08e4d0c5190f01871e0569b6290b86760085d99f17eb4e7e6b58feb8d6249", - "0x8c35d22f459d77ca4c0b0b5035869766d60d182b9716ab3e8879e066478899a8", - "0xf4aac2fbe33f03554bfeb559ea2690ed8521caa4be961e61c91ac9a1530dce7a" - ], - "rootHash": "0xf85f275b6b06c233fc62ecb5992cd3b3396982ecef9c9508e615c6f528c8fc25", - "proofs": [ - { - "items": [ - "0xe12c22d4f162d9a012c9319233da5d3e923cc5e1029b8f90e47249c9ab256b35", - "0x513bf90be61a0fa9099a23510fc22436cf364f837d7d455fc6b13903874e98b9", - "0xf1a7824906429ae42bb2a9e36258e8268eeedf08a7adc3394841a0636ceed444" - ], - "order": 4 - }, - { - "items": [ - "0x11da6d1f761ddf9bdb4c9d6e5303ebd41f61858d0a5647a1a7bfe089bf921be9", - "0x513bf90be61a0fa9099a23510fc22436cf364f837d7d455fc6b13903874e98b9", - "0xf1a7824906429ae42bb2a9e36258e8268eeedf08a7adc3394841a0636ceed444" - ], - "order": 5 - }, - { - "items": [ - "0x8c039ff7caa17ccebfcadc44bd9fce6a4b6699c4d03de2e3349aa1dc11193cd7", - "0xacd5fdc9438204fb30c9154587515c2d12d1e5da66bc4f766be92319504443c1", - "0xf1a7824906429ae42bb2a9e36258e8268eeedf08a7adc3394841a0636ceed444" - ], - "order": 6 - }, - { - "items": [ - "0x7b0aa1735e5ba58d3236316c671fe4f00ed366ee72417c9ed02a53a8019e85b8", - "0xacd5fdc9438204fb30c9154587515c2d12d1e5da66bc4f766be92319504443c1", - "0xf1a7824906429ae42bb2a9e36258e8268eeedf08a7adc3394841a0636ceed444" - ], - "order": 7 - }, - { - "items": [ - "0x8c35d22f459d77ca4c0b0b5035869766d60d182b9716ab3e8879e066478899a8", - "0xf4aac2fbe33f03554bfeb559ea2690ed8521caa4be961e61c91ac9a1530dce7a", - "0xb5d6bae5432161e6ce0fdfd28ea26011f581ad68335e77cf68864f4911879257" - ], - "order": 2 - }, - { - "items": [ - "0x26a08e4d0c5190f01871e0569b6290b86760085d99f17eb4e7e6b58feb8d6249", - "0xf4aac2fbe33f03554bfeb559ea2690ed8521caa4be961e61c91ac9a1530dce7a", - "0xb5d6bae5432161e6ce0fdfd28ea26011f581ad68335e77cf68864f4911879257" - ], - "order": 3 - }, - { - "items": [ - "0x2fc249826fa000037981cc3446a7e0ad347c8446525dc7958723ea3afc7209de", - "0xb5d6bae5432161e6ce0fdfd28ea26011f581ad68335e77cf68864f4911879257" - ], - "order": 0 - } - ] -} diff --git a/core/packages/contracts/test/archive/libs/mmr_proof.test.ts b/core/packages/contracts/test/archive/libs/mmr_proof.test.ts deleted file mode 100644 index b4e00b0b61e13..0000000000000 --- a/core/packages/contracts/test/archive/libs/mmr_proof.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { ethers, expect, loadFixture } from "../setup" -import { MMRProofWrapper__factory } from "../../src" -import fixture7leaves from "./data/mmr-fixture-data-7-leaves.json" -import fixture15leaves from "./data/mmr-fixture-data-15-leaves.json" - -describe("MMR Proof Verification", function () { - async function fixture() { - let [owner] = await ethers.getSigners() - - let verifier = await new MMRProofWrapper__factory(owner).deploy() - await verifier.deployed() - - return { verifier } - } - - describe("7-leaf, 11-node MMR", function () { - before(function () { - console.log(" 7-leaf MMR: ") - console.log(" ") - console.log(" Height 3 | 7") - console.log(" Height 2 | 3 6 10") - console.log(" Height 1 | 1 2 4 5 8 9 11") - console.log(" | |--|---|--|---|--|-----|-") - console.log("Leaf indexes | 0 1 2 3 4 5 6") - }) - - fixture7leaves.proofs.forEach((proof, i) => { - it(`should verify valid proof for leaf index ${i}`, async () => { - let { verifier } = await loadFixture(fixture) - - expect( - await verifier.verifyLeafProof( - fixture7leaves.rootHash, - fixture7leaves.leaves[i], - fixture7leaves.proofs[i].items, - fixture7leaves.proofs[i].order - ) - ).to.be.true - }) - - it(`should reject invalid proof for leaf index ${i}`, async () => { - let { verifier } = await loadFixture(fixture) - - let j = i + 1 - if (j >= fixture7leaves.proofs.length) { - j = 0 - } - expect( - await verifier.verifyLeafProof( - fixture7leaves.rootHash, - fixture7leaves.leaves[i], - fixture7leaves.proofs[j].items, - fixture7leaves.proofs[j].order - ) - ).to.be.false - }) - }) - }) - - describe("15-leaf, 26-node MMR", function () { - before(function () { - console.log( - " 15-leaf MMR: " - ) - console.log( - " " - ) - console.log( - " Height 4 | 15 " - ) - console.log( - " Height 3 | 7 14 22 " - ) - console.log( - " Height 2 | 3 6 10 13 18 21 25 " - ) - console.log( - " Height 1 | 1 2 4 5 8 9 11 12 16 17 19 20 23 24 26 " - ) - console.log( - " | |--|---|--|---|--|-----|---|---|---|----|---|----|---|---|---" - ) - console.log( - "Leaf indexes | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 " - ) - }) - - fixture15leaves.proofs.forEach((proof, i) => { - it(`should verify valid proof for leaf index ${i}`, async () => { - let { verifier } = await loadFixture(fixture) - - expect( - await verifier.verifyLeafProof( - fixture15leaves.rootHash, - fixture15leaves.leaves[i], - fixture15leaves.proofs[i].items, - fixture15leaves.proofs[i].order - ) - ).to.be.true - }) - - it(`should reject invalid proof for leaf index ${i}`, async () => { - let { verifier } = await loadFixture(fixture) - - let j = i + 1 - if (j >= fixture15leaves.proofs.length) { - j = 0 - } - expect( - await verifier.verifyLeafProof( - fixture15leaves.rootHash, - fixture15leaves.leaves[i], - fixture15leaves.proofs[j].items, - fixture15leaves.proofs[j].order - ) - ).to.be.false - }) - }) - }) - - it("ge report", async function () { - let { verifier } = await loadFixture(fixture) - let gasuse = await verifier.estimateGas.verifyLeafProof( - fixture15leaves.rootHash, - fixture15leaves.leaves[7], - fixture15leaves.proofs[7].items, - fixture15leaves.proofs[7].order - ) - console.log(gasuse) - }) -}) diff --git a/core/packages/contracts/test/mocks/OutboundQueueMock.sol b/core/packages/contracts/test/mocks/OutboundQueueMock.sol deleted file mode 100644 index 5af8d648d37f0..0000000000000 --- a/core/packages/contracts/test/mocks/OutboundQueueMock.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import {IOutboundQueue} from "../../src/IOutboundQueue.sol"; -import {ParaID} from "../../src/Types.sol"; - -contract OutboundQueueMock is IOutboundQueue { - uint64 public nonce; - - function submit(ParaID dest, bytes calldata payload) external payable { - emit Message(dest, ++nonce, payload); - } -} diff --git a/core/packages/contracts/test/mocks/ParachainClientMock.sol b/core/packages/contracts/test/mocks/ParachainClientMock.sol deleted file mode 100644 index b8bcdf83ecc10..0000000000000 --- a/core/packages/contracts/test/mocks/ParachainClientMock.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import "../../src/IParachainClient.sol"; -import "../../src/ParachainClient.sol"; -import "../../src/BeefyClient.sol"; - -contract ParachainClientMock is ParachainClient { - constructor(BeefyClient _client, uint32 _parachainID) ParachainClient(_client, _parachainID) {} - - function verifyCommitment(bytes32, bytes calldata parachainHeaderProof) external pure override returns (bool) { - if (keccak256(parachainHeaderProof) == keccak256(bytes("validProof"))) { - return true; - } else { - return false; - } - } - - function createParachainHeaderMerkleLeaf_public(ParachainHeader memory header) external view returns (bytes32) { - return createParachainHeaderMerkleLeaf(header); - } - - function isCommitmentInHeaderDigest_public(bytes32 commitment, ParachainHeader memory header) - external - pure - returns (bool) - { - return isCommitmentInHeaderDigest(commitment, header); - } -} diff --git a/core/packages/contracts/test/mocks/RecipientMock.sol b/core/packages/contracts/test/mocks/RecipientMock.sol deleted file mode 100644 index 3e030f8281b9f..0000000000000 --- a/core/packages/contracts/test/mocks/RecipientMock.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import {IRecipient} from "../../src/IRecipient.sol"; -import {ParaID} from "../../src/Types.sol"; - -contract RecipientMock is IRecipient { - bool shouldFail; - bool shouldPanic; - bool shouldConsumeAllGas; - - error Failed(); - - event Called(); - - function setShouldFail() external { - shouldFail = true; - shouldPanic = false; - shouldConsumeAllGas = false; - } - - function setShouldPanic() external { - shouldFail = false; - shouldPanic = true; - shouldConsumeAllGas = false; - } - - function setShouldConsumeAllGas() external { - shouldFail = false; - shouldPanic = false; - shouldConsumeAllGas = true; - } - - function handle(ParaID, bytes calldata) external { - if (shouldFail) { - revert("failed"); - } - if (shouldPanic) { - assert(false); - } - if (shouldConsumeAllGas) { - while (true) {} - } - emit Called(); - } -} diff --git a/core/packages/contracts/test/mocks/UpgradeTaskMock.sol b/core/packages/contracts/test/mocks/UpgradeTaskMock.sol deleted file mode 100644 index 782768fbdba82..0000000000000 --- a/core/packages/contracts/test/mocks/UpgradeTaskMock.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.19; - -import {AccessControl} from "openzeppelin/access/AccessControl.sol"; - -import {UpgradeTask} from "../../src/UpgradeTask.sol"; -import {Registry} from "../../src/Registry.sol"; -import {OutboundQueue} from "../../src/OutboundQueue.sol"; -import {ParaID} from "../../src/Types.sol"; - -contract UpgradeTaskMock is UpgradeTask { - constructor(Registry registry) UpgradeTask(registry) {} - function handle(ParaID origin, bytes calldata message) external override onlyRole(SENDER_ROLE) {} - - // In this simple upgrade we just update a fee parameter - function run() external override { - OutboundQueue(resolve(keccak256("OutboundQueue"))).updateFee(2 ether); - } -} - -contract FailingUpgradeTaskMock is UpgradeTask { - constructor(Registry registry) UpgradeTask(registry) {} - function handle(ParaID origin, bytes calldata message) external override onlyRole(SENDER_ROLE) {} - - function run() external pure override { - revert("failed"); - } -} diff --git a/core/packages/test/scripts/configure-beefy.sh b/core/packages/test/scripts/configure-beefy.sh deleted file mode 100755 index 37f7d2ff9979b..0000000000000 --- a/core/packages/test/scripts/configure-beefy.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash -set -eu - -source scripts/set-env.sh - -configure_beefy() -{ - pushd "$contract_dir" - - npx ts-node ./scripts/configure-beefy.ts - - local current_id=$(jq .validatorSets.current.id $beefy_state_file) - local current_length=$(jq .validatorSets.current.length $beefy_state_file) - local current_root=$(jq .validatorSets.current.root $beefy_state_file) - - local next_id=$(jq .validatorSets.next.id $beefy_state_file) - local next_length=$(jq .validatorSets.next.length $beefy_state_file) - local next_root=$(jq .validatorSets.next.root $beefy_state_file) - - # remove double quote before cast - local current_root=$(sed -e 's/^"//' -e 's/"$//' <<< $current_root) - local next_root=$(sed -e 's/^"//' -e 's/"$//' <<< $next_root) - - echo "Transact call to initialize BeefyClient" - # sometimes sending transact with cast will fail on the goerli network - # temporarily resolved by manually setting --gas-price and --gas-limit - cast send $(address_for BeefyClient) \ - "initialize(uint64,(uint128,uint128,bytes32),(uint128,uint128,bytes32))" \ - --rpc-url $eth_endpoint_http \ - --private-key $PRIVATE_KEY \ - --gas-limit $eth_gas_limit \ - $beefy_start_block \ - \($current_id,$current_length,$current_root\) \ - \($next_id,$next_length,$next_root\) - popd -} - -if [ -z "${from_start_services:-}" ]; then - echo "config contracts only!" - configure_beefy - wait -fi diff --git a/core/pnpm-workspace.yaml b/core/pnpm-workspace.yaml deleted file mode 100644 index 9dfcfe2566490..0000000000000 --- a/core/pnpm-workspace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -packages: - - "packages/test" - - "packages/api" - - "packages/contracts" diff --git a/cumulus b/cumulus index 825df854624bd..c6cf3c37f94f5 160000 --- a/cumulus +++ b/cumulus @@ -1 +1 @@ -Subproject commit 825df854624bdca89ae7cd47c0d77892a502f96b +Subproject commit c6cf3c37f94f5433ca3bfa2751083b9d1add1f35 diff --git a/docs/architecture/apps/dot.md b/docs/architecture/apps/dot.md index f6bdd57637a25..6c28622f33ba3 100644 --- a/docs/architecture/apps/dot.md +++ b/docs/architecture/apps/dot.md @@ -14,7 +14,7 @@ Obviously this means that if wDOT accounts have very small amounts of dust that ## Implementation -* [DOTApp smart contract](../../../core/packages/contracts/contracts/DOTApp.sol) +* [DOTApp smart contract](../../../contracts/contracts/DOTApp.sol) * [DOTApp pallet](https://github.com/Snowfork/snowbridge/tree/main/parachain/pallets/dot-app) wDOT is implemented using this ERC-777 contract: [WrappedToken](../../../ethereum/contracts/WrappedToken.sol) diff --git a/docs/architecture/apps/erc20.md b/docs/architecture/apps/erc20.md index d2ddb26862029..4ca967a297718 100644 --- a/docs/architecture/apps/erc20.md +++ b/docs/architecture/apps/erc20.md @@ -24,7 +24,7 @@ Our approach is to just document clearly that rebasing tokens are not supported. The app consists of two peer components which communicate via [channels](../channels/): -* [ERC20App smart contract](../../../core/packages/contracts/contracts/ERC20App.sol) +* [ERC20App smart contract](../../../contracts/contracts/ERC20App.sol) * [ERC20App pallet](https://github.com/Snowfork/snowbridge/tree/main/parachain/pallets/erc20-app) On the parachain, the wrapped tokens are stored in a FRAME [assets](https://github.com/paritytech/substrate/tree/master/frame/assets) pallet using numeric identifiers allocated by our [asset-registry](https://github.com/Snowfork/snowbridge/tree/main/parachain/pallets/asset-registry) pallet. diff --git a/docs/architecture/apps/ether.md b/docs/architecture/apps/ether.md index b3b59a935a2b3..f7bdb81723116 100644 --- a/docs/architecture/apps/ether.md +++ b/docs/architecture/apps/ether.md @@ -14,7 +14,7 @@ Given that native Ether has 18 decimal places, this means that a maximum of $$3. The app consists of two peer components which communicate via [channels](../channels/): -* [EtherApp smart contract](../../../core/packages/contracts/contracts/ETHApp.sol) +* [EtherApp smart contract](../../../contracts/contracts/ETHApp.sol) * [EtherApp pallet](https://github.com/Snowfork/snowbridge/tree/main/parachain/pallets/eth-app) On the parachain, the wrapped Ether is stored in a FRAME [assets](https://github.com/paritytech/substrate/tree/master/frame/assets) pallet with an asset id of `0`. diff --git a/docs/architecture/verification/polkadot/README.md b/docs/architecture/verification/polkadot/README.md index 68a2c5d3d8882..99373171d8e6e 100644 --- a/docs/architecture/verification/polkadot/README.md +++ b/docs/architecture/verification/polkadot/README.md @@ -18,11 +18,11 @@ In collaboration with W3F, we have designed a protocol where the light client ne In the EVM there is no cryptographically-secure source of randomness. Instead we make our update protocol crypto-economically secure through an [Interactive Update Protocol](interactive-update-protocol.md). In this protocol, a candidate commitment is verified over 2 transactions. At a high-level it works like this: -1. In the [first transaction](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/core/packages/contracts/src/BeefyClient.sol#L199), the relayer submits the commitment, and an initial bitfield claiming which validators have signed the commitment. +1. In the [first transaction](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/contracts/src/BeefyClient.sol#L199), the relayer submits the commitment, and an initial bitfield claiming which validators have signed the commitment. 2. The relayer must then wait [MAX\_SEED\_LOOKAHEAD](https://eth2book.info/bellatrix/part3/config/preset/#max\_seed\_lookahead) blocks. -3. The relayer submits a [second transaction](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/core/packages/contracts/src/BeefyClient.sol#L227) to reveal and commit to a random seed, derived from Ethereum's [RANDAO](https://eips.ethereum.org/EIPS/eip-4399). -4. The relayer [requests](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/core/packages/contracts/src/BeefyClient.sol#L524) from the light client a bitfield with $$\lceil log_2{(3N)}\rceil$$randomly-chosen validators sampled from the initial bitfield.​ -5. The relayer sends a [third transaction](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/core/packages/contracts/src/BeefyClient.sol#L255) with signatures for all the validators specified in the final bitfield +3. The relayer submits a [second transaction](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/contracts/src/BeefyClient.sol#L227) to reveal and commit to a random seed, derived from Ethereum's [RANDAO](https://eips.ethereum.org/EIPS/eip-4399). +4. The relayer [requests](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/contracts/src/BeefyClient.sol#L524) from the light client a bitfield with $$\lceil log_2{(3N)}\rceil$$randomly-chosen validators sampled from the initial bitfield.​ +5. The relayer sends a [third transaction](https://github.com/Snowfork/snowbridge/blob/54b62c92445635164d1414af742e26b56a097003/contracts/src/BeefyClient.sol#L255) with signatures for all the validators specified in the final bitfield 6. The light client verifies all validator signatures in the third transaction to ensure: 1. The provided validators are in the current validator set 2. The provided validators are in the final bitfield @@ -48,5 +48,5 @@ Working backwards, if the BEEFY light client successfully verifies a parachain h Solidity Contracts: -* [BeefyClient.sol](../../../../core/packages/contracts/src/BeefyClient.sol) -* [ParachainClient.sol](../../../../core/packages/contracts/src/ParachainClient.sol) +* [BeefyClient.sol](../../../../contracts/src/BeefyClient.sol) +* [ParachainClient.sol](../../../../contracts/src/ParachainClient.sol) diff --git a/docs/other/quick-start-guide.md b/docs/other/quick-start-guide.md index e338f814ba9da..d8cb95e7c6b60 100644 --- a/docs/other/quick-start-guide.md +++ b/docs/other/quick-start-guide.md @@ -112,7 +112,7 @@ This guide uses the root of the `$HOME/` folder for all source code. ``` 4. Edit `.envrc` and `direnv allow` - In the `core/packages/test` subfolder of the `snowbridge` repo copy the envrc-example. + In the `web/packages/test` subfolder of the `snowbridge` repo copy the envrc-example. ```bash cp .envrc-example .envrc @@ -126,7 +126,7 @@ This guide uses the root of the `$HOME/` folder for all source code. direnv allow ``` - In the `core/packages/contracts` subfolder of the `snowbridge` repo copy the envrc-example. Here we do not need to edit the `.envrc` as defaults are set. + In the `contracts` subfolder of the `snowbridge` repo copy the envrc-example. Here we do not need to edit the `.envrc` as defaults are set. ```bash cp .envrc-example .envrc @@ -137,7 +137,7 @@ This guide uses the root of the `$HOME/` folder for all source code. 1. Start up the local E2E test stack -In a separate terminal change directory to the `core/packages/test` subfolder of the `snowbridge` repo. Run `start-services.sh` script to start the bridge. +In a separate terminal change directory to the `web/packages/test` subfolder of the `snowbridge` repo. Run `start-services.sh` script to start the bridge. ```bash scripts/start-services.sh @@ -157,7 +157,7 @@ When this is complete `Testnet has been initialized` will be printed to the term The bridge requires a certain amount of funds (SnowDOT and SnowETH) in order for Incentivized channels to be used. The bootstrap process are the first two test cases and needs to be run before other tests will pass. - In the `core/packages/test` subfolder of the `snowbridge` repo run the bootstrap tests: + In the `web/packages/test` subfolder of the `snowbridge` repo run the bootstrap tests: ```bash pnpm test:integration test/bootstrap.js @@ -189,28 +189,28 @@ When this is complete `Testnet has been initialized` will be printed to the term The Lodestar log file is `/tmp/snowbridge/lodestar.log`. 2. Relaychain - The relay chain log files are in the `core/packages/test` subdirectory of the `snowbridge` repo. `alice.log`, `bob.log`, `charlie.log` + The relay chain log files are in the `web/packages/test` subdirectory of the `snowbridge` repo. `alice.log`, `bob.log`, `charlie.log` The relay chain can be accessed via the polkadot.js web using the following url: [https://polkadot.js.org/apps/?rpc=ws%3A%2F%127.0.0.1%3A9944#/explorer](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2Flocalhost%3A9944#/explorer) 3. Parachain - The Snowbridge parachain log files are in the `core/packages/test` subdirectory of the `snowbridge` repo. `11144.log`, `11155.log` + The Snowbridge parachain log files are in the `web/packages/test` subdirectory of the `snowbridge` repo. `11144.log`, `11155.log` The Snowbridge parachain can be accessed via the polkadot.js web using the following url: [https://polkadot.js.org/apps/?rpc=ws%3A%2F%127.0.0.1%3A11144#/explorer](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2Flocalhost%3A11144#/explorer) 4. Test Parachain - The third-party test parachain log files are in the `core/packages/test` subdirectory of the `snowbridge` repo. `13144.log`, `13155.log` + The third-party test parachain log files are in the `web/packages/test` subdirectory of the `snowbridge` repo. `13144.log`, `13155.log` The Snowbridge Test parachain can be accessed via the polkadot.js web using the following url: [https://polkadot.js.org/apps/?rpc=ws%3A%2F%127.0.0.1%3A13144#/explorer](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2Flocalhost%3A13144#/explorer) 5. Relayers -The relayers log files can be found in the `core/packages/test` subdirectory of the `snowbridge` repo. +The relayers log files can be found in the `web/packages/test` subdirectory of the `snowbridge` repo. * `beacon-relay.log` * `parachain-relay.log` diff --git a/flake.lock b/flake.lock index 588f85e7f4d97..67f23f3598329 100644 --- a/flake.lock +++ b/flake.lock @@ -54,11 +54,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1685870001, - "narHash": "sha256-ijUNyTvT/dT9JOcsNiVtu/u1Eicf0HqQ7SPyZ5yRU84=", + "lastModified": 1688462028, + "narHash": "sha256-+43L9rwbNC1cO0LrinxjaolmyIH/STpL67uf2s6+6C0=", "owner": "shazow", "repo": "foundry.nix", - "rev": "c80b4ea3bdce135164a7aac78aafb7c619b2dd23", + "rev": "e8fb5553c880942ac5215fb210ada54841605c62", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index c4da1438121ea..bac1052ca7249 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,8 @@ jq moreutils typos + ripgrep + tree # ps for zombienet, required in pure shells on Linux ps @@ -46,8 +48,17 @@ # relayer go + gotools + gopls + go-outline + gocode + gopkgs + gocode-gomod + godef + golint mage revive + delve # parachain clang @@ -69,17 +80,15 @@ # explicitly setting HOME allows go to infer these vars # export HOME=~ - export PATH=~/go/bin/:$PATH + export GOPATH=$PWD/go + export PATH=$GOPATH/bin:$PATH eval "$(direnv hook bash)" # LIBCLANG_PATH points rocksdb to a clang.so on Linux export LIBCLANG_PATH="$(readlink -f ${pkgs.clang}/resource-root/include | xargs dirname | xargs dirname | xargs dirname)" - echo "Initializing Snowbridge Dev Environment..." - (cd core && pnpm install) - - cowsay "Snowbridge Dev Environment Ready" + cowsay "Development Environment Ready" ''; }; } diff --git a/go.work b/go.work new file mode 100644 index 0000000000000..dc4f7fca0e104 --- /dev/null +++ b/go.work @@ -0,0 +1,3 @@ +go 1.20 + +use ./relayer diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000000000..01c8f4911a66f --- /dev/null +++ b/go.work.sum @@ -0,0 +1,42 @@ +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index 0bb6b50fcf310..98adb20f28eed 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "bounded-collections" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbd1d11282a1eb134d3c3b7cf8ce213b5161c6e5f73fb1b98618482c606b64" +checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" dependencies = [ "log", "parity-scale-codec", @@ -795,7 +795,7 @@ dependencies = [ [[package]] name = "ethabi-decode" version = "1.3.3" -source = "git+https://github.com/snowfork/ethabi-decode.git?branch=master#6f63405bb33ef4365a1c62b72d499fa0f448118e" +source = "git+https://github.com/Snowfork/ethabi-decode.git?branch=master#6f63405bb33ef4365a1c62b72d499fa0f448118e" dependencies = [ "ethereum-types", "tiny-keccak 1.5.0", @@ -1889,6 +1889,22 @@ dependencies = [ "sp-timestamp", ] +[[package]] +name = "pallet-transaction-payment" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=master#e976964644d951a1eefaaa85f1d7c7d58211ddf7" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "parity-bytes" version = "0.1.2" @@ -1897,9 +1913,9 @@ checksum = "16b56e3a2420138bdb970f84dfb9c774aea80fa0e7371549eedec0d80c209c67" [[package]] name = "parity-scale-codec" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637935964ff85a605d114591d4d2c13c5d1ba2806dae97cea6bf180238a749ac" +checksum = "2287753623c76f953acd29d15d8100bcab84d29db78fb6f352adb3c53e83b967" dependencies = [ "arrayvec 0.7.2", "bitvec", @@ -1912,9 +1928,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "2b6937b5e67bfba3351b87b040d48352a2fcb6ad72f81855412ce97b45c8f110" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2075,9 +2091,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" dependencies = [ "unicode-ident", ] @@ -2620,6 +2636,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex-literal", "parity-scale-codec", "scale-info", "snowbridge-core", @@ -2628,12 +2645,15 @@ dependencies = [ "sp-runtime", "sp-std", "xcm", + "xcm-builder", + "xcm-executor", ] [[package]] name = "snowbridge-core" version = "0.1.1" dependencies = [ + "ethabi-decode", "frame-support", "frame-system", "parity-scale-codec", @@ -2666,7 +2686,6 @@ dependencies = [ "serde", "serde-big-array", "serde_json", - "snowbridge-testutils", "sp-core", "sp-io", "sp-runtime", @@ -2694,7 +2713,6 @@ dependencies = [ "snowbridge-beacon-primitives", "snowbridge-core", "snowbridge-ethereum", - "snowbridge-testutils", "sp-core", "sp-io", "sp-keyring", @@ -2801,19 +2819,10 @@ dependencies = [ "sp-runtime", "sp-std", "xcm", + "xcm-builder", "xcm-executor", ] -[[package]] -name = "snowbridge-testutils" -version = "0.1.0" -dependencies = [ - "ethereum-types", - "rustc-hex", - "serde", - "serde_json", -] - [[package]] name = "sp-api" version = "4.0.0-dev" @@ -4119,12 +4128,35 @@ dependencies = [ "xcm-procedural", ] +[[package]] +name = "xcm-builder" +version = "0.9.43" +source = "git+https://github.com/paritytech/polkadot?branch=master#b6b74fdf546c14bf9ac93c03916abda9ee33a52f" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log", + "pallet-transaction-payment", + "parity-scale-codec", + "polkadot-parachain", + "scale-info", + "sp-arithmetic", + "sp-io", + "sp-runtime", + "sp-std", + "sp-weights", + "xcm", + "xcm-executor", +] + [[package]] name = "xcm-executor" version = "0.9.43" source = "git+https://github.com/paritytech/polkadot?branch=master#b6b74fdf546c14bf9ac93c03916abda9ee33a52f" dependencies = [ "environmental", + "frame-benchmarking", "frame-support", "impl-trait-for-tuples", "log", diff --git a/parachain/Cargo.toml b/parachain/Cargo.toml index e4fec4827f7dc..cdd61f8b83fbe 100644 --- a/parachain/Cargo.toml +++ b/parachain/Cargo.toml @@ -2,7 +2,6 @@ members = [ "primitives/core", "primitives/ethereum", - "primitives/testutils", "primitives/router", "pallets/inbound-queue", "pallets/outbound-queue", diff --git a/parachain/README.md b/parachain/README.md index 3c722cb66e568..51e2be123b6d1 100644 --- a/parachain/README.md +++ b/parachain/README.md @@ -3,7 +3,7 @@ ## Configuration Note: This section is not necessary for local development, as there are scripts to auto-configure the parachain in the -[test directory](../core/packages/test). +[test directory](../web/packages/test). For a fully operational chain, further configuration of the initial chain spec is required. The specific configuration will depend heavily on your environment, so this guide will remain high-level. @@ -18,7 +18,7 @@ Now edit the spec and configure the following: 2. Contract addresses for the Ether, Erc20, and Dot apps. 3. Authorized principal for the basic channel -For an example configuration, consult the [setup script](https://github.com/Snowfork/snowbridge/blob/main/core/packages/test/scripts/start-services.sh) for our local development stack. Specifically the `start_polkadot_launch` bash function. +For an example configuration, consult the [setup script](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/scripts/start-services.sh) for our local development stack. Specifically the `start_polkadot_launch` bash function. ## Tests @@ -108,7 +108,7 @@ target/release/snowbridge benchmark pallet \ To generate `minimal` test data and benchmarking data, make sure to start the local E2E setup to spin up a local beacon node instance to connect to: ```bash -cd core/packages/test +cd web/packages/test ./scripts/start-services.sh ``` @@ -127,7 +127,7 @@ We only use the mainnet spec for generating fixtures for pallet weight benchmark To generate the data we can connect to the Lodestar Goerli public node. The script already connects to the Lodestar node, so no need to start up additional services. In the event of the Lodestar node not being available, you can start up your own stack with these commands: ```bash -cd core/packages/test +cd web/packages/test ./scripts/start-goerli.sh ``` diff --git a/parachain/pallets/control/Cargo.toml b/parachain/pallets/control/Cargo.toml index 9cb1e394282f7..f3fa0511d2255 100644 --- a/parachain/pallets/control/Cargo.toml +++ b/parachain/pallets/control/Cargo.toml @@ -28,12 +28,13 @@ sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } xcm = { git = "https://github.com/paritytech/polkadot.git", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot.git", branch = "master", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot.git", branch = "master", default-features = false } ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } - [dev-dependencies] - +hex-literal = { version = "0.4.1" } [features] default = ["std"] @@ -48,7 +49,13 @@ std = [ "sp-io/std", "sp-runtime/std", "xcm/std", + "xcm-builder/std", + "xcm-executor/std", "ethabi/std" ] -runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks" +] try-runtime = ["frame-support/try-runtime"] diff --git a/parachain/pallets/control/src/benchmarking.rs b/parachain/pallets/control/src/benchmarking.rs index 76a564442c1c6..828f511d8265a 100644 --- a/parachain/pallets/control/src/benchmarking.rs +++ b/parachain/pallets/control/src/benchmarking.rs @@ -7,17 +7,30 @@ use super::*; use crate::Pallet as Template; use frame_benchmarking::v2::*; use frame_system::RawOrigin; +use sp_core::Get; #[benchmarks] mod benchmarks { use super::*; #[benchmark] - fn upgrade() -> Result<(), BenchmarkError> { - let upgrade_task = H160::repeat_byte(3); + fn upgrade(x: Linear<0, { T::MaxUpgradeDataSize::get() - 1 }>) -> Result<(), BenchmarkError> { + let impl_address = H160::repeat_byte(1); + let impl_code_hash = H256::repeat_byte(1); + let params: Vec = (0..x).map(|_| 1u8).collect(); #[extrinsic_call] - _(RawOrigin::Root, upgrade_task); + _(RawOrigin::Root, impl_address, impl_code_hash, Some(params)); + + Ok(()) + } + + #[benchmark] + fn create_agent() -> Result<(), BenchmarkError> { + let caller: T::AccountId = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); Ok(()) } diff --git a/parachain/pallets/control/src/lib.rs b/parachain/pallets/control/src/lib.rs index 50a7a080a619d..ff1a2430a23ab 100644 --- a/parachain/pallets/control/src/lib.rs +++ b/parachain/pallets/control/src/lib.rs @@ -1,10 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork +//! Governance API for controlling the Ethereum side of the bridge #![cfg_attr(not(feature = "std"), no_std)] -/// Edit this file to define custom logic or remove it if it is not needed. -/// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// pub use pallet::*; #[cfg(test)] @@ -19,17 +17,20 @@ mod benchmarking; pub mod weights; pub use weights::*; -use snowbridge_core::{ContractId, OutboundMessage, OutboundQueue as OutboundQueueTrait, ParaId}; -use sp_core::{H160, H256, U256}; +use snowbridge_core::outbound::{Command, Message, OutboundQueue as OutboundQueueTrait, ParaId}; +use snowbridge_core::AgentId; +use sp_core::{H160, H256}; use sp_runtime::traits::Hash; use sp_std::prelude::*; +use xcm::prelude::*; +use xcm_executor::traits::ConvertLocation; -use ethabi::Token; +pub use pallet::*; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::pallet_prelude::*; + use frame_support::{pallet_prelude::*, traits::EnsureOrigin}; use frame_system::pallet_prelude::*; #[pallet::pallet] @@ -38,61 +39,132 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// General-purpose hasher type MessageHasher: Hash; + + /// Send messages to Ethereum type OutboundQueue: OutboundQueueTrait; + + /// The ID of this parachain type OwnParaId: Get; - type GovernanceProxyContract: Get; + + /// Max size of params passed to initializer of the new implementation contract + type MaxUpgradeDataSize: Get; + + /// Origin check for `create_agent` + type CreateAgentOrigin: EnsureOrigin; + + /// Converts MultiLocation to H256 in a way that is stable across multiple versions of XCM + type AgentHashedDescription: ConvertLocation; + + /// The universal location + type UniversalLocation: Get; + + /// Location of the relay chain + type RelayLocation: Get; + type WeightInfo: WeightInfo; } - #[pallet::storage] - #[pallet::getter(fn something)] - pub type Something = StorageValue<_, u32>; - #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - UpgradeTaskSubmitted { upgrade_task: H160 }, + /// An Upgrade message was sent to the Gateway + Upgrade { impl_address: H160, impl_code_hash: H256, params_hash: Option }, + /// An CreateAgent message was sent to the Gateway + CreateAgent { location: MultiLocation, agent_id: AgentId }, } #[pallet::error] pub enum Error { + UpgradeDataTooLarge, SubmissionFailed, + LocationConversionFailed, + AgentAlreadyCreated, } + #[pallet::storage] + pub type Agents = StorageMap<_, Twox64Concat, AgentId, (), OptionQuery>; + #[pallet::call] impl Pallet { + /// Sends a message to the Gateway contract to upgrade itself. + /// + /// - `origin`: Must be `Root`. + /// - `impl_address`: The address of the new implementation contract. + /// - `impl_code_hash`: The codehash of `impl_address`. + /// - `params`: An optional list of ABI-encoded parameters for the implementation + /// contract's `initialize(bytes) function. If `None`, the initialization function is not called. #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::upgrade())] - pub fn upgrade(origin: OriginFor, upgrade_task: H160) -> DispatchResult { + #[pallet::weight(T::WeightInfo::upgrade(params.clone().map_or(0, |d| d.len() as u32)))] + pub fn upgrade( + origin: OriginFor, + impl_address: H160, + impl_code_hash: H256, + params: Option>, + ) -> DispatchResult { ensure_root(origin)?; - let message = OutboundMessage { - id: T::MessageHasher::hash(upgrade_task.as_ref()), - origin: T::OwnParaId::get(), - gateway: T::GovernanceProxyContract::get(), - payload: Self::encode_upgrade_payload(upgrade_task), - }; + ensure!( + params.clone().map_or(0, |d| d.len() as u32) < T::MaxUpgradeDataSize::get(), + Error::::UpgradeDataTooLarge + ); - let ticket = - T::OutboundQueue::validate(&message).map_err(|_| Error::::SubmissionFailed)?; + let params_hash = params.as_ref().map(|p| T::MessageHasher::hash(p)); - T::OutboundQueue::submit(ticket).map_err(|_| Error::::SubmissionFailed)?; + let message = Message { + origin: T::OwnParaId::get(), + command: Command::Upgrade { impl_address, impl_code_hash, params }, + }; + Self::submit_outbound(message)?; - Self::deposit_event(Event::::UpgradeTaskSubmitted { upgrade_task }); + Self::deposit_event(Event::::Upgrade { impl_address, impl_code_hash, params_hash }); + Ok(()) + } + /// Sends a message to the Gateway contract to create a new Agent representing `origin` + /// + /// - `origin`: Must be `MultiLocation` + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::create_agent())] + pub fn create_agent(origin: OriginFor) -> DispatchResult { + let mut location: MultiLocation = T::CreateAgentOrigin::ensure_origin(origin)?; + + // Normalize all locations relative to the relay chain unless its the relay itself. + let relay_location = T::RelayLocation::get(); + if location != relay_location { + location + .reanchor(&relay_location, T::UniversalLocation::get()) + .or(Err(Error::::LocationConversionFailed))?; + } + + // Hash the location to produce an agent id + let agent_id = T::AgentHashedDescription::convert_location(&location) + .ok_or(Error::::LocationConversionFailed)?; + + // Record the agent id or fail if it has already been created + if let Some(_) = Agents::::get(agent_id) { + return Err(Error::::AgentAlreadyCreated.into()); + } + Agents::::insert(agent_id, ()); + + let message = Message { + origin: T::OwnParaId::get(), + command: Command::CreateAgent { agent_id } + }; + Self::submit_outbound(message)?; + + Self::deposit_event(Event::::CreateAgent { location, agent_id }); Ok(()) } } impl Pallet { - fn encode_upgrade_payload(upgrade_task: H160) -> Vec { - ethabi::encode(&vec![Token::Tuple(vec![ - Token::Uint(U256::from(0u64)), - Token::Bytes(ethabi::encode(&vec![Token::Tuple(vec![Token::Address( - upgrade_task, - )])])), - ])]) + fn submit_outbound(message: Message) -> DispatchResult { + let ticket = T::OutboundQueue::validate(&message).map_err(|_| Error::::SubmissionFailed)?; + T::OutboundQueue::submit(ticket).map_err(|_| Error::::SubmissionFailed)?; + Ok(()) } } } diff --git a/parachain/pallets/control/src/mock.rs b/parachain/pallets/control/src/mock.rs index f99ed5fd9207a..b39ef360f1605 100644 --- a/parachain/pallets/control/src/mock.rs +++ b/parachain/pallets/control/src/mock.rs @@ -2,18 +2,27 @@ // SPDX-FileCopyrightText: 2023 Snowfork use crate as snowbridge_control; use frame_support::{ + pallet_prelude::EnsureOrigin, parameter_types, - traits::{ConstU16, ConstU64}, + traits::{ConstU16, ConstU64, OriginTrait}, }; -use snowbridge_core::{ContractId, ParaId}; + +#[cfg(feature = "runtime-benchmarks")] +use frame_benchmarking::v2::whitelisted_caller; + +use snowbridge_core::outbound::{Message, MessageHash, ParaId, SubmitError}; use sp_core::H256; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, + AccountId32, }; +use xcm::prelude::*; +use xcm_builder::{DescribeAllTerminal, DescribeFamily, HashedDescription}; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; +type AccountId = AccountId32; // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( @@ -38,7 +47,7 @@ impl frame_system::Config for Test { type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = u64; + type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; type RuntimeEvent = RuntimeEvent; @@ -56,20 +65,143 @@ impl frame_system::Config for Test { parameter_types! { pub const OwnParaId: ParaId = ParaId::new(1013); - pub const GovernanceProxyContract: ContractId = ContractId::new([3u8; 32]); + pub const MaxUpgradeDataSize: u32 = 1024; pub const SS58Prefix: u8 = 42; + pub const AnyNetwork: Option = None; + pub const RelayNetwork: Option = Some(NetworkId::Kusama); + pub const RelayLocation: MultiLocation = MultiLocation::parent(); + pub UniversalLocation: InteriorMultiLocation = + X2(GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013)); +} + +static ORIGIN_TABLE: &[([u8; 32], MultiLocation)] = &[ + // Case 1: Relay chain + ([1; 32], MultiLocation { parents: 1, interior: Here }), + // Case 2: Local AccountId32 + ( + [2; 32], + MultiLocation { + parents: 0, + interior: X1(Junction::AccountId32 { network: None, id: [0; 32] }), + }, + ), + // Case 3: Local AccountKey20 + ( + [3; 32], + MultiLocation { + parents: 0, + interior: X1(Junction::AccountKey20 { network: None, key: [0; 20] }), + }, + ), + // Case 4: Local Pallet + ([4; 32], MultiLocation { parents: 0, interior: X1(Junction::PalletInstance(1)) }), + // Case 5: Sibling Chain + ([5; 32], MultiLocation { parents: 1, interior: X1(Junction::Parachain(1000)) }), + // Case 6: Sibling Chain Pallet + ( + [6; 32], + MultiLocation { + parents: 1, + interior: X2(Junction::Parachain(1000), Junction::PalletInstance(1)), + }, + ), + // Case 7: Sibling Chain AccountId32 + ( + [7; 32], + MultiLocation { + parents: 1, + interior: X2( + Junction::Parachain(1000), + Junction::AccountId32 { network: None, id: [0; 32] }, + ), + }, + ), + // Case 8: Sibling Chain AccountKey20 + ( + [8; 32], + MultiLocation { + parents: 1, + interior: X2( + Junction::Parachain(1000), + Junction::AccountKey20 { network: None, key: [0; 20] }, + ), + }, + ), + // Case 9: Bad Multi Locations + ( + [9; 32], + MultiLocation { + parents: 1, + interior: X2(Junction::Parachain(1000), Junction::Parachain(1000)), + }, + ), + // Case 10: Bad Validate Message + ([10; 32], MultiLocation { parents: 1, interior: X1(Junction::Parachain(1001)) }), + // Case 11: Bad Submit Message + ([11; 32], MultiLocation { parents: 1, interior: X1(Junction::Parachain(1002)) }), +]; + +pub struct EnsureOriginFromTable; +impl EnsureOrigin for EnsureOriginFromTable { + type Success = MultiLocation; + + fn try_origin(outer: RuntimeOrigin) -> Result { + let account = outer.clone().into_signer().ok_or(outer.clone())?; + + // Benchmarking + #[cfg(feature = "runtime-benchmarks")] + { + if account == whitelisted_caller() { + return Ok(MultiLocation::new(1, Here)); + } + } + + // test cases + let key: [u8; 32] = account.into(); + for entry in ORIGIN_TABLE { + if entry.0 == key { + return Ok(entry.1); + } + } + Err(outer) + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(RuntimeOrigin::signed([0u8; 32].into())) + } +} + +pub struct MockOutboundQueue; +impl snowbridge_control::OutboundQueueTrait for MockOutboundQueue { + type Ticket = Message; + + fn validate(message: &Message) -> Result { + Ok(message.clone()) + } + + fn submit(_ticket: Self::Ticket) -> Result { + Ok(MessageHash::zero()) + } } impl snowbridge_control::Config for Test { type RuntimeEvent = RuntimeEvent; type OwnParaId = OwnParaId; - type OutboundQueue = (); - type GovernanceProxyContract = GovernanceProxyContract; + type OutboundQueue = MockOutboundQueue; type MessageHasher = BlakeTwo256; + type MaxUpgradeDataSize = MaxUpgradeDataSize; + type CreateAgentOrigin = EnsureOriginFromTable; + type UniversalLocation = UniversalLocation; + type RelayLocation = RelayLocation; + type AgentHashedDescription = HashedDescription>; type WeightInfo = (); } // Build genesis storage according to the mock runtime. pub fn new_test_ext() -> sp_io::TestExternalities { - frame_system::GenesisConfig::default().build_storage::().unwrap().into() + let storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut ext: sp_io::TestExternalities = storage.into(); + ext.execute_with(|| System::set_block_number(1)); + ext } diff --git a/parachain/pallets/control/src/tests.rs b/parachain/pallets/control/src/tests.rs index 2fb7903711e55..07368c70ed87e 100644 --- a/parachain/pallets/control/src/tests.rs +++ b/parachain/pallets/control/src/tests.rs @@ -1,2 +1,173 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork +use crate::mock::*; +use crate::*; +use hex_literal::hex; +use sp_core::H256; +use sp_runtime::AccountId32; +use sp_runtime::DispatchError::BadOrigin; + +#[test] +fn create_agent_with_unknown_origin_yields_bad_origin() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([0; 32])); + frame_support::assert_noop!(EthereumControl::create_agent(origin), BadOrigin); + }); +} + +#[test] +fn create_agent_with_bad_multi_location_yields_location_conversion_failed() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([9; 32])); + frame_support::assert_noop!( + EthereumControl::create_agent(origin), + Error::::LocationConversionFailed + ); + }); +} + +#[test] +fn create_agent_with_relaychain_origin_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([1; 32])); + let expected_agent_id = + H256(hex!("d9380024e49afa1ac89c0127fea210bb6b431b10dafefab8061bd88ac25d17a5")); + let expected_multi_location = MultiLocation { parents: 1, interior: Here }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} + +#[test] +fn create_agent_with_local_account32_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([2; 32])); + let expected_agent_id = + H256(hex!("57fc5659083f0cc883125ccb2c380a1397a3b08434586b8647cc44bcb3647d29")); + let expected_multi_location = MultiLocation { + parents: 0, + interior: X2(Parachain(1013), Junction::AccountId32 { network: None, id: [0; 32] }), + }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} + +#[test] +fn create_agent_with_local_account20_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([3; 32])); + let expected_agent_id = + H256(hex!("fc29ec0899cf25874937d04b9b011760fa5dc5cf59af1448abefd389bba7bea2")); + let expected_multi_location = MultiLocation { + parents: 0, + interior: X2(Parachain(1013), AccountKey20 { network: None, key: [0; 20] }), + }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} + +#[test] +fn create_agent_with_local_pallet_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([4; 32])); + let expected_agent_id = + H256(hex!("ed40c69763094b73c0e3585eeb576fbcee6999123ff1f1beac1f05f5f4c9d945")); + let expected_multi_location = + MultiLocation { parents: 0, interior: X2(Parachain(1013), PalletInstance(1)) }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} + +#[test] +fn create_agent_with_sibling_chain_origin_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([5; 32])); + let expected_agent_id = + H256(hex!("72456f48efed08af20e5b317abf8648ac66e86bb90a411d9b0b713f7364b75b4")); + let expected_multi_location = MultiLocation { parents: 0, interior: X1(Parachain(1000)) }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} + +#[test] +fn create_agent_with_sibling_chain_account32_origin_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([7; 32])); + let expected_agent_id = + H256(hex!("fb804b0b77f9c9d69a16d7a45de81225ab8da112e0eb8d2e0229c78086b8927a")); + let expected_multi_location = MultiLocation { + parents: 0, + interior: X2(Parachain(1000), Junction::AccountId32 { network: None, id: [0; 32] }), + }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} + +#[test] +fn create_agent_with_sibling_chain_account20_origin_yields_success() { + new_test_ext().execute_with(|| { + let origin = RuntimeOrigin::signed(AccountId32::new([8; 32])); + let expected_agent_id = + H256(hex!("74867486f141b159ba1e295bf616d740429269879d4291a12a65eaedbb4b502a")); + let expected_multi_location = MultiLocation { + parents: 0, + interior: X2(Parachain(1000), AccountKey20 { network: None, key: [0; 20] }), + }; + + assert!(!Agents::::contains_key(expected_agent_id)); + assert_eq!(EthereumControl::create_agent(origin), Ok(())); + assert!(Agents::::contains_key(expected_agent_id)); + + System::assert_last_event(RuntimeEvent::EthereumControl(crate::Event::CreateAgent { + location: expected_multi_location, + agent_id: expected_agent_id, + })); + }); +} diff --git a/parachain/pallets/control/src/weights.rs b/parachain/pallets/control/src/weights.rs index ef38bd112bcb2..fe7dccb91bb6d 100644 --- a/parachain/pallets/control/src/weights.rs +++ b/parachain/pallets/control/src/weights.rs @@ -35,13 +35,18 @@ use core::marker::PhantomData; /// Weight functions needed for pallet_template. pub trait WeightInfo { - fn upgrade() -> Weight; + fn upgrade(data_size: u32) -> Weight; + fn create_agent() -> Weight; } /// Weights for pallet_template using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - fn upgrade() -> Weight { + fn upgrade(_data_size: u32) -> Weight { + Weight::from_parts(9_000_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + fn create_agent() -> Weight { Weight::from_parts(9_000_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -49,7 +54,11 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - fn upgrade() -> Weight { + fn upgrade(_data_size: u32) -> Weight { + Weight::from_parts(9_000_000, 0) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + fn create_agent() -> Weight { Weight::from_parts(9_000_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/parachain/pallets/ethereum-beacon-client/Cargo.toml b/parachain/pallets/ethereum-beacon-client/Cargo.toml index e4d5ebc4c6cd8..c0b338095c8f6 100644 --- a/parachain/pallets/ethereum-beacon-client/Cargo.toml +++ b/parachain/pallets/ethereum-beacon-client/Cargo.toml @@ -37,7 +37,6 @@ bp-runtime = { git = "https://github.com/Snowfork/cumulus.git", branch = "snowbr rand = "0.8.5" sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -snowbridge-testutils = { path = "../../primitives/testutils" } serde_json = "1.0.96" hex-literal = { version = "0.4.1" } pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/parachain/pallets/ethereum-beacon-client/src/lib.rs b/parachain/pallets/ethereum-beacon-client/src/lib.rs index 5cbbf519c7b87..3ed2b901392e2 100644 --- a/parachain/pallets/ethereum-beacon-client/src/lib.rs +++ b/parachain/pallets/ethereum-beacon-client/src/lib.rs @@ -26,13 +26,14 @@ use primitives::{ CompactBeaconState, CompactExecutionHeader, ExecutionHeaderState, ForkData, ForkVersion, ForkVersions, PublicKeyPrepared, SigningData, }; -use snowbridge_core::{Message, RingBufferMap, Verifier}; +use snowbridge_core::{ + inbound::{Message, Proof, Verifier}, + RingBufferMap, +}; use sp_core::H256; use sp_std::prelude::*; pub use weights::WeightInfo; -use snowbridge_core::Proof; - use functions::{ compute_epoch, compute_period, decompress_sync_committee_bits, sync_committee_sum, }; @@ -118,7 +119,8 @@ pub mod pallet { BLSPreparePublicKeysFailed, BLSVerificationFailed(BlsError), InvalidUpdateSlot, - /// The given update is not in the expected period, or the given next sync committee does not match the next sync committee in storage. + /// The given update is not in the expected period, or the given next sync committee does + /// not match the next sync committee in storage. InvalidSyncCommitteeUpdate, ExecutionHeaderTooFarBehind, ExecutionHeaderSkippedBlock, @@ -345,9 +347,9 @@ pub mod pallet { // committee period. let max_latency = config::EPOCHS_PER_SYNC_COMMITTEE_PERIOD * config::SLOTS_PER_EPOCH; ensure!( - latest_execution_state.beacon_slot == 0 || - latest_finalized_state.slot < - latest_execution_state.beacon_slot + max_latency as u64, + latest_execution_state.beacon_slot == 0 + || latest_finalized_state.slot + < latest_execution_state.beacon_slot + max_latency as u64, Error::::ExecutionHeaderTooFarBehind ); Ok(()) @@ -365,8 +367,8 @@ pub mod pallet { // Verify update does not skip a sync committee period. ensure!( - update.signature_slot > update.attested_header.slot && - update.attested_header.slot >= update.finalized_header.slot, + update.signature_slot > update.attested_header.slot + && update.attested_header.slot >= update.finalized_header.slot, Error::::InvalidUpdateSlot ); // Retrieve latest finalized state. @@ -386,12 +388,12 @@ pub mod pallet { // Verify update is relevant. let update_attested_period = compute_period(update.attested_header.slot); - let update_has_next_sync_committee = !>::exists() && - (update.next_sync_committee_update.is_some() && - update_attested_period == store_period); + let update_has_next_sync_committee = !>::exists() + && (update.next_sync_committee_update.is_some() + && update_attested_period == store_period); ensure!( - update.attested_header.slot > latest_finalized_state.slot || - update_has_next_sync_committee, + update.attested_header.slot > latest_finalized_state.slot + || update_has_next_sync_committee, Error::::IrrelevantUpdate ); @@ -594,7 +596,7 @@ pub mod pallet { let state = >::get(block_root) .ok_or(Error::::ExpectedFinalizedHeaderNotStored)?; if update.header.slot != state.slot { - return Err(Error::::ExpectedFinalizedHeaderNotStored.into()) + return Err(Error::::ExpectedFinalizedHeaderNotStored.into()); } }, } @@ -784,13 +786,13 @@ pub mod pallet { /// Returns the fork version based on the current epoch. pub(super) fn select_fork_version(fork_versions: &ForkVersions, epoch: u64) -> ForkVersion { if epoch >= fork_versions.capella.epoch { - return fork_versions.capella.version + return fork_versions.capella.version; } if epoch >= fork_versions.bellatrix.epoch { - return fork_versions.bellatrix.version + return fork_versions.bellatrix.version; } if epoch >= fork_versions.altair.epoch { - return fork_versions.altair.version + return fork_versions.altair.version; } fork_versions.genesis.version diff --git a/parachain/pallets/ethereum-beacon-client/src/mock.rs b/parachain/pallets/ethereum-beacon-client/src/mock.rs index 6c8488cbc0caf..4c8be79517e0a 100644 --- a/parachain/pallets/ethereum-beacon-client/src/mock.rs +++ b/parachain/pallets/ethereum-beacon-client/src/mock.rs @@ -9,17 +9,16 @@ use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; -use hex_literal::hex; -use snowbridge_core::Proof; #[cfg(not(feature = "beacon-spec-mainnet"))] pub mod minimal { use super::*; use crate::config; - use std::{fs::File, path::PathBuf}; use primitives::CompactExecutionHeader; - use snowbridge_core::Message; + use snowbridge_core::inbound::{Message, Proof}; + use std::{fs::File, path::PathBuf}; + use hex_literal::hex; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -150,7 +149,7 @@ pub mod minimal { load_fixture("next-finalized-header-update.minimal.json").unwrap() } - pub fn get_message_verification_payload() -> Message{ + pub fn get_message_verification_payload() -> Message { Message { data: hex!("f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").to_vec(), proof: Proof { @@ -169,12 +168,15 @@ pub mod minimal { } } - pub fn get_message_verification_header() -> CompactExecutionHeader{ - CompactExecutionHeader{ - parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04").into(), + pub fn get_message_verification_header() -> CompactExecutionHeader { + CompactExecutionHeader { + parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04") + .into(), block_number: 55, - state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3").into(), - receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").into(), + state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3") + .into(), + receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb") + .into(), } } } diff --git a/parachain/pallets/ethereum-beacon-client/src/tests.rs b/parachain/pallets/ethereum-beacon-client/src/tests.rs index da4ac5c4bb01e..963b358189202 100644 --- a/parachain/pallets/ethereum-beacon-client/src/tests.rs +++ b/parachain/pallets/ethereum-beacon-client/src/tests.rs @@ -12,7 +12,7 @@ use hex_literal::hex; use primitives::{CompactExecutionHeader, ForkVersions, NextSyncCommitteeUpdate, Fork, ExecutionHeaderState}; use rand::{thread_rng, Rng}; use sp_core::H256; -use snowbridge_core::{Verifier, RingBufferMap}; +use snowbridge_core::{RingBufferMap, inbound::Verifier}; /// Arbitrary hash used for tests and invalid hashes. const TEST_HASH: [u8; 32] = hex!["5f6f02af29218292d21a69b64a794a7c0873b3e0f54611972863706e8cbdf371"]; diff --git a/parachain/pallets/inbound-queue/Cargo.toml b/parachain/pallets/inbound-queue/Cargo.toml index fc4cce2662936..b83a4ec84b800 100644 --- a/parachain/pallets/inbound-queue/Cargo.toml +++ b/parachain/pallets/inbound-queue/Cargo.toml @@ -37,7 +37,7 @@ ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "eth [dev-dependencies] frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -snowbridge-ethereum-beacon-client = { path = "../../pallets/ethereum-beacon-client", default-features = false } +snowbridge-ethereum-beacon-client = { path = "../../pallets/ethereum-beacon-client" } hex-literal = { version = "0.4.1" } rlp = { version = "0.5" } @@ -62,8 +62,6 @@ std = [ "ethabi/std", "xcm/std", "bp-runtime/std", - "snowbridge-beacon-primitives/std", - "snowbridge-ethereum-beacon-client/std", ] runtime-benchmarks = [ "snowbridge-core/runtime-benchmarks", diff --git a/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs b/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs index 33a84c7215617..ebce56ae10137 100644 --- a/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs +++ b/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs @@ -1,7 +1,7 @@ use super::*; use hex_literal::hex; use snowbridge_beacon_primitives::CompactExecutionHeader; -use snowbridge_core::{Message, Proof}; +use snowbridge_core::inbound::{Message, Proof}; pub struct InboundQueueTest { pub execution_header: CompactExecutionHeader, @@ -11,24 +11,24 @@ pub struct InboundQueueTest { pub fn make_create_message() -> InboundQueueTest { InboundQueueTest{ execution_header: CompactExecutionHeader{ - parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04").into(), - block_number: 55, - state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3").into(), - receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").into(), + parent_hash: hex!("de4afc4d33a83815cde0a6dd95c8e52d9e01231d67d5b5a387ec70994a96108f").into(), + block_number: 61, + state_root: hex!("7bfc6d7a49869863d621989dad7fa26c610470e65473a7e5cab87af67fc6976c").into(), + receipts_root: hex!("a2686fe1aa2f66ada774373ced7952f3591a7830b9161eec5d16149747253779").into(), }, message: Message { - data: hex!("f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").to_vec(), + data: hex!("f8fb94eda338e4dc46038493b885327842fd3e301cab39f842a0d56f1b8dfd3ba41f19c499ceec5f9546f61befa5f10398a75d7dba53a219fecea000000000000000000000000000000000000000000000000000000000000003e8b8a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000034000f000000000000000057a2d4ff0c3866d96556884bf09fecdd7ccd530c87d1f7fdfee7f651fabc8bfcb6e086c278b77a7d3500000000000000000000000000").to_vec(), proof: Proof { - block_hash: hex!("05aaa60b0f27cce9e71909508527264b77ee14da7b5bf915fcc4e32715333213").into(), + block_hash: hex!("565f5dc872af9351abd1ba4974753169a98f028ef2c2ef3bb6d4eea4c6519eac").into(), tx_index: 0, data: (vec![ - hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").to_vec(), - hex!("d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c185510").to_vec(), - hex!("b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646").to_vec(), + hex!("a2686fe1aa2f66ada774373ced7952f3591a7830b9161eec5d16149747253779").to_vec(), + hex!("77cc88c126ea5be62d3caea280da54cd051a05dadc03e4ecf69621da86ff9e12").to_vec(), + hex!("61ced6f6c7533351a0e60916ee60bbe4f7c49efae74bb898d06b1ae975b38c51").to_vec(), ], vec![ - hex!("f90131a0b601337b3aa10a671caa724eba641e759399979856141d3aea6b6b4ac59b889ba00c7d5dd48be9060221a02fb8fa213860b4c50d47046c8fa65ffaba5737d569e0a094601b62a1086cd9c9cb71a7ebff9e718f3217fd6e837efe4246733c0a196f63a06a4b0dd0aefc37b3c77828c8f07d1b7a2455ceb5dbfd3c77d7d6aeeddc2f7e8ca0d6e8e23142cdd8ec219e1f5d8b56aa18e456702b195deeaa210327284d42ade4a08a313d4c87023005d1ab631bbfe3f5de1e405d0e66d0bef3e033f1e5711b5521a0bf09a5d9a48b10ade82b8d6a5362a15921c8b5228a3487479b467db97411d82fa0f95cccae2a7c572ef3c566503e30bac2b2feb2d2f26eebf6d870dcf7f8cf59cea0d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c1855108080808080808080").to_vec(), - hex!("f851a0b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646a060a634b9280e3a23fb63375e7bbdd9ab07fd379ab6a67e2312bbc112195fa358808080808080808080808080808080").to_vec(), - hex!("f9030820b9030402f90300018301d6e2b9010000000000000800000000000020040008000000000000000000000000400000008000000000000000000000000000000000000000000000000000000000042010000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000002000000000000000000000000200000000000000200000000000100000000040000001000200008000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000f901f5f87a942ffa5ecdbe006d30397c7636d3e015eee251369ff842a0c965575a00553e094ca7c5d14f02e107c258dda06867cbf9e0e69f80e71bbcc1a000000000000000000000000000000000000000000000000000000000000003e8a000000000000000000000000000000000000000000000000000000000000003e8f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000f858948cf6147918a5cbb672703f879f385036f8793a24e1a01449abf21e49fd025f33495e77f7b1461caefdd3d4bb646424a3f445c4576a5ba0000000000000000000000000440edffa1352b13227e8ee646f3ea37456dec701").to_vec(), + hex!("f90131a0697ffa69627df903e12004769f4a763d81cc2d947fa75e47996112144c7d07d1a0a755881c8727579c18865b63c20117773ddb5579acdb3ed493557bb6aa5a1117a0ba0c4975a96270e63526f20073d129931e4b1dfc4dbd477a92c7d587afaad6a1a0e2c388369c489466c7c03d0a9f3cb294c8fc659015a395f7dc7b1b28eaf18ef4a027fcb43431cd39b449624b39ceb0017fce919e14e2ca77c28f8ab981b01aa637a05f3c3aac495f2fbc982da582c8e62ac05adb1e0552a1b9e81be96028094cbcc4a0a3f115af7400065f142ec8edea4f2000a4bcf6394869df85ecb9d27d75e344daa0b5f12f70fc3e4078273e59aba72683905d11e1c4b1a68858a6e53d3c50f65b93a077cc88c126ea5be62d3caea280da54cd051a05dadc03e4ecf69621da86ff9e128080808080808080").to_vec(), + hex!("f851a061ced6f6c7533351a0e60916ee60bbe4f7c49efae74bb898d06b1ae975b38c51a0f0baa5ff24cde5e3bcc6e5394b30e10e97cca31d002d68769883293d0ebbd569808080808080808080808080808080").to_vec(), + hex!("f9026a20b9026602f902620183013defb9010000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000400000000000000000000000000000000000000000000000000000000000000000000000020200000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000014f90157f85894eda338e4dc46038493b885327842fd3e301cab39e1a0f78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7ea000000000000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7df8fb94eda338e4dc46038493b885327842fd3e301cab39f842a0d56f1b8dfd3ba41f19c499ceec5f9546f61befa5f10398a75d7dba53a219fecea000000000000000000000000000000000000000000000000000000000000003e8b8a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000034000f000000000000000057a2d4ff0c3866d96556884bf09fecdd7ccd530c87d1f7fdfee7f651fabc8bfcb6e086c278b77a7d3500000000000000000000000000").to_vec(), ]), }, }, diff --git a/parachain/pallets/inbound-queue/src/benchmarking/mod.rs b/parachain/pallets/inbound-queue/src/benchmarking/mod.rs index 3f168ca62e57b..5c6396948ba83 100644 --- a/parachain/pallets/inbound-queue/src/benchmarking/mod.rs +++ b/parachain/pallets/inbound-queue/src/benchmarking/mod.rs @@ -14,7 +14,7 @@ mod benchmarks { use crate::benchmarking::fixtures::make_create_message; use hex_literal::hex; - const OUTBOUND_QUEUE_ADDRESS: [u8; 20] = hex!["ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0"]; + const GATEWAY_ADDRESS: [u8; 20] = hex!["eda338e4dc46038493b885327842fd3e301cab39"]; #[benchmark] fn submit() -> Result<(), BenchmarkError> { @@ -27,16 +27,29 @@ mod benchmarks { create_message.execution_header, ); - >::put(create_allowlist::()); + >::put(H160(GATEWAY_ADDRESS)); let dest_para: ParaId = 1000u32.into(); let sovereign_account = dest_para.into_account_truncating(); + let minimum_balance = T::Token::minimum_balance(); + let minimum_balance_u32: u32 = minimum_balance + .try_into() + .unwrap_or_else(|_| panic!("unable to cast minimum balance to u32")); + + // Make sure the sovereign balance is enough. This is a funny number, because + // in some cases the minimum balance is really high, in other cases very low. + // e.g. on bridgehub the minium balance is 33333, on test it is 1. So this equation makes + // it is at least twice the minimum balance (so as to satisfy the minimum balance + // requirement, and then some (in case the minimum balance is very low, even lower + // than the relayer reward fee). + let sovereign_balance = (minimum_balance_u32 * 2) + 5000; + // So that the receiving account exists - let _ = T::Token::mint_into(&caller, T::Token::minimum_balance().into()); + let _ = T::Token::mint_into(&caller, minimum_balance.into()); // Fund the sovereign account (parachain sovereign account) so it can transfer a reward // fee to the caller account - let _ = T::Token::mint_into(&sovereign_account, 10000u32.into()); + let _ = T::Token::mint_into(&sovereign_account, sovereign_balance.into()); #[block] { @@ -51,19 +64,7 @@ mod benchmarks { impl_benchmark_test_suite!( InboundQueue, - crate::test::new_tester::(crate::H160::default()), + crate::test::new_tester(crate::H160::default()), crate::test::Test ); - - fn create_allowlist() -> BoundedBTreeSet - where - T: Config, - { - let allowlist: BoundedBTreeSet = - BTreeSet::from_iter(vec![OUTBOUND_QUEUE_ADDRESS.into()].into_iter()) - .try_into() - .expect("exceeded bound"); - - allowlist - } } diff --git a/parachain/pallets/inbound-queue/src/envelope.rs b/parachain/pallets/inbound-queue/src/envelope.rs index 581604b6a15a2..3ce9dfd71d52e 100644 --- a/parachain/pallets/inbound-queue/src/envelope.rs +++ b/parachain/pallets/inbound-queue/src/envelope.rs @@ -7,12 +7,12 @@ use snowbridge_ethereum::{log::Log, H160}; use sp_core::RuntimeDebug; use sp_std::{convert::TryFrom, prelude::*}; -// Used to decode a raw Ethereum log into an [`Envelope`]. +// Used to decode an OutboundMessageAccepted log into an [`Envelope`]. static EVENT_ABI: &Event = &Event { - signature: "Message(uint32,uint64,bytes)", + signature: "OutboundMessageAccepted(uint256,uint64,bytes)", inputs: &[ - Param { kind: ParamKind::Uint(32), indexed: true }, - Param { kind: ParamKind::Uint(64), indexed: true }, + Param { kind: ParamKind::Uint(256), indexed: true }, + Param { kind: ParamKind::Uint(64), indexed: false }, Param { kind: ParamKind::Bytes, indexed: false }, ], anonymous: false, @@ -22,7 +22,7 @@ static EVENT_ABI: &Event = &Event { #[derive(Clone, RuntimeDebug)] pub struct Envelope { /// The address of the outbound queue on Ethereum that emitted this message as an event log - pub outbound_queue_address: H160, + pub gateway: H160, /// The destination parachain. pub dest: ParaId, /// A nonce for enforcing replay protection and ordering. @@ -57,6 +57,6 @@ impl TryFrom for Envelope { _ => return Err(EnvelopeDecodeError), }; - Ok(Self { outbound_queue_address: log.address, dest, nonce, payload }) + Ok(Self { gateway: log.address, dest, nonce, payload }) } } diff --git a/parachain/pallets/inbound-queue/src/lib.rs b/parachain/pallets/inbound-queue/src/lib.rs index 9c4f7e657c67b..990f987eaac75 100644 --- a/parachain/pallets/inbound-queue/src/lib.rs +++ b/parachain/pallets/inbound-queue/src/lib.rs @@ -19,32 +19,28 @@ mod test; use codec::DecodeAll; use frame_support::{ - storage::bounded_btree_set::BoundedBTreeSet, - traits::fungible::{Inspect, Mutate}, - DefaultNoBound, + traits::{ + fungible::{Inspect, Mutate}, + GenesisBuild, + }, + DefaultNoBound, CloneNoBound, EqNoBound, PartialEqNoBound }; use frame_system::ensure_signed; -use snowbridge_core::ParaId; use sp_core::H160; use sp_runtime::traits::AccountIdConversion; -use sp_std::{collections::btree_set::BTreeSet, convert::TryFrom, vec::Vec}; +use sp_std::convert::TryFrom; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use xcm::v3::{send_xcm, Junction::*, Junctions::*, MultiLocation, SendError}; +use snowbridge_core::ParaId; use envelope::Envelope; -use snowbridge_core::{Message, Verifier}; +use snowbridge_core::inbound::{Message, Verifier}; use snowbridge_router_primitives::inbound; - -use xcm::v3::{send_xcm, Junction::*, Junctions::*, MultiLocation, SendError}; - pub use weights::WeightInfo; -use frame_support::{CloneNoBound, EqNoBound, PartialEqNoBound}; - -use codec::{Decode, Encode}; - -use scale_info::TypeInfo; - type BalanceOf = - <::Token as Inspect<::AccountId>>::Balance; + <::Token as Inspect<::AccountId>>::Balance; #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] pub enum MessageDispatchResult { @@ -80,18 +76,20 @@ pub mod pallet { pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The verifier for inbound messages from Ethereum type Verifier: Verifier; + /// Message relayers are rewarded with this asset type Token: Mutate; + /// The amount to reward message relayers type Reward: Get>; + /// XCM message sender type XcmSender: SendXcm; type WeightInfo: WeightInfo; - type AllowListLength: Get; - #[cfg(feature = "runtime-benchmarks")] type Helper: BenchmarkHelper; } @@ -102,32 +100,37 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - MessageReceived { dest: ParaId, nonce: u64, result: MessageDispatchResult }, - AllowListAdded { address: sp_core::H160 }, - AllowListRemoved { address: sp_core::H160 }, + /// A message was received from Ethereum + MessageReceived { + /// The destination parachain + dest: ParaId, + /// The message nonce + nonce: u64, + /// The result of the message dispatch + result: MessageDispatchResult + }, } #[pallet::error] pub enum Error { /// Message came from an invalid outbound channel on the Ethereum side. - InvalidOutboundQueue, + InvalidGateway, /// Message has an invalid envelope. InvalidEnvelope, /// Message has an unexpected nonce. InvalidNonce, /// Cannot convert location InvalidAccountConversion, - /// Allow list is full. - AllowListFull, /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } + /// The address of the Gateway contract on Ethereum #[pallet::storage] - #[pallet::getter(fn peer)] - pub type AllowList = - StorageValue<_, BoundedBTreeSet, ValueQuery>; + #[pallet::getter(fn gateway)] + pub type Gateway = StorageValue<_, H160, ValueQuery>; + /// The current nonce for each parachain #[pallet::storage] pub type Nonce = StorageMap<_, Twox64Concat, ParaId, u64, ValueQuery>; @@ -148,24 +151,15 @@ pub mod pallet { #[pallet::genesis_config] #[derive(DefaultNoBound)] - pub struct GenesisConfig { - /// Allow list of outbound channels from ethereum - pub allowlist: Vec, - /// Initial pallet owner. - pub owner: Option, + pub struct GenesisConfig { + /// The address of the Gateway contract on Ethereum + pub gateway: H160, } #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { + impl GenesisBuild for GenesisConfig { fn build(&self) { - let allowlist: BoundedBTreeSet = - BTreeSet::from_iter(self.allowlist.clone().into_iter()) - .try_into() - .expect("exceeded bound"); - >::put(allowlist); - if let Some(ref owner) = self.owner { - PalletOwner::::put(owner); - } + Gateway::::put(self.gateway); } } @@ -178,6 +172,7 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// Submit an inbound message originating from the Gateway contract on Ethereum #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::submit())] pub fn submit(origin: OriginFor, message: Message) -> DispatchResult { @@ -189,12 +184,8 @@ pub mod pallet { // Decode log into an Envelope let envelope = Envelope::try_from(log).map_err(|_| Error::::InvalidEnvelope)?; - // Verify that the message was submitted to us from a known - // outbound channel on the ethereum side - let allowlist = >::get(); - if !allowlist.contains(&envelope.outbound_queue_address) { - return Err(Error::::InvalidOutboundQueue.into()) - } + // Verify that the message was submitted from the known Gateway contract + ensure!(Gateway::::get() == envelope.gateway, Error::::InvalidGateway,); // Verify message nonce >::try_mutate(envelope.dest, |nonce| -> DispatchResult { @@ -215,34 +206,22 @@ pub mod pallet { // succeed even if the message was not successfully decoded or dispatched. // Attempt to decode message - let decoded_message = - match inbound::VersionedMessage::decode_all(&mut envelope.payload.as_ref()) { - Ok(inbound::VersionedMessage::V1(decoded_message)) => decoded_message, - Err(_) => { - Self::deposit_event(Event::MessageReceived { - dest: envelope.dest, - nonce: envelope.nonce, - result: MessageDispatchResult::InvalidPayload, - }); - return Ok(()) - }, - }; - - // Attempt to convert to XCM - let sibling_para = - MultiLocation { parents: 1, interior: X1(Parachain(envelope.dest.into())) }; - let xcm = match decoded_message.try_into() { - Ok(xcm) => xcm, + let xcm = match inbound::VersionedMessage::decode_all(&mut envelope.payload.as_ref()) { + Ok(inbound::VersionedMessage::V1(message_v1)) => message_v1.into(), Err(_) => { Self::deposit_event(Event::MessageReceived { dest: envelope.dest, nonce: envelope.nonce, result: MessageDispatchResult::InvalidPayload, }); - return Ok(()) + return Ok(()); }, }; + // Attempt to convert to XCM + let sibling_para = + MultiLocation { parents: 1, interior: X1(Parachain(envelope.dest.into())) }; + // Attempt to send XCM to a sibling parachain match send_xcm::(sibling_para, xcm) { Ok(_) => Self::deposit_event(Event::MessageReceived { @@ -261,32 +240,10 @@ pub mod pallet { } #[pallet::call_index(1)] - #[pallet::weight({100_000_000})] - pub fn add_allow_list(origin: OriginFor, address: sp_core::H160) -> DispatchResult { + #[pallet::weight((T::DbWeight::get().writes(1), DispatchClass::Normal))] + pub fn set_gateway(origin: OriginFor, gateway: H160) -> DispatchResult { ensure_root(origin)?; - - let success = >::mutate(|allowlist| allowlist.try_insert(address).is_ok()); - - if success { - Self::deposit_event(Event::AllowListAdded { address }); - - Ok(()) - } else { - Err(Error::::AllowListFull.into()) - } - } - - #[pallet::call_index(2)] - #[pallet::weight({100_000_000})] - pub fn remove_allow_list(origin: OriginFor, address: sp_core::H160) -> DispatchResult { - ensure_root(origin)?; - - let removed = >::mutate(|allowlist| allowlist.remove(&address)); - - if removed { - Self::deposit_event(Event::AllowListRemoved { address }); - } - + Gateway::::put(gateway); Ok(()) } diff --git a/parachain/pallets/inbound-queue/src/test.rs b/parachain/pallets/inbound-queue/src/test.rs index a958c42ec851a..68228e70f2ca0 100644 --- a/parachain/pallets/inbound-queue/src/test.rs +++ b/parachain/pallets/inbound-queue/src/test.rs @@ -6,9 +6,9 @@ use frame_support::{ assert_noop, assert_ok, dispatch::DispatchError, parameter_types, - traits::{ConstU64, Everything, GenesisBuild}, + traits::{ConstU64, Everything}, }; -use sp_core::{ConstU32, H160, H256}; +use sp_core::{H160, H256}; use sp_keyring::AccountKeyring as Keyring; use sp_runtime::{ testing::Header, @@ -18,7 +18,7 @@ use sp_runtime::{ use sp_std::convert::From; use snowbridge_beacon_primitives::{Fork, ForkVersions}; -use snowbridge_core::{Message, Proof}; +use snowbridge_core::inbound::{Message, Proof}; use snowbridge_ethereum::Log; use hex_literal::hex; @@ -147,7 +147,6 @@ impl inbound_queue::Config for Test { type Reward = ConstU64<100>; type XcmSender = (); type WeightInfo = (); - type AllowListLength = ConstU32<2>; #[cfg(feature = "runtime-benchmarks")] type Helper = Test; } @@ -166,19 +165,14 @@ fn expect_events(e: Vec) { assert_eq!(last_events(e.len()), e); } -pub fn new_tester(outbound_queue_address: H160) -> sp_io::TestExternalities { - new_tester_with_config::(inbound_queue::GenesisConfig { - allowlist: vec![outbound_queue_address], - owner: None, - }) +pub fn new_tester(gateway: H160) -> sp_io::TestExternalities { + new_tester_with_config(inbound_queue::GenesisConfig { gateway }) } -pub fn new_tester_with_config( - config: inbound_queue::GenesisConfig, -) -> sp_io::TestExternalities { +pub fn new_tester_with_config(config: inbound_queue::GenesisConfig) -> sp_io::TestExternalities { let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); - GenesisBuild::::assimilate_storage(&config, &mut storage).unwrap(); + GenesisBuild::::assimilate_storage(&config, &mut storage).unwrap(); let mut ext: sp_io::TestExternalities = storage.into(); ext.execute_with(|| System::set_block_number(1)); @@ -202,19 +196,19 @@ fn parse_dest(message: Message) -> ParaId { } // The originating channel address for the messages below -const OUTBOUND_QUEUE_ADDRESS: [u8; 20] = hex!["87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"]; +const GATEWAY_ADDRESS: [u8; 20] = hex!["EDa338E4dC46038493b885327842fD3E301CaB39"]; -const OUTBOUND_QUEUE_EVENT_LOG: [u8; 254] = hex!( +const OUTBOUND_QUEUE_EVENT_LOG: [u8; 253] = hex!( " - f8fc9487d1f7fdfee7f651fabc8bfcb6e086c278b77a7df863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b880000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000290001f8f7758fbcefd546eaeff7de24aff666b6228e730000000000e8890423c78a00000000000000000000000000000000000000000000000000000000000000 + f8fb94eda338e4dc46038493b885327842fd3e301cab39f842a0d56f1b8dfd3ba41f19c499ceec5f9546f61befa5f10398a75d7dba53a219fecea000000000000000000000000000000000000000000000000000000000000003e8b8a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000034000f000000000000000057a2d4ff0c3866d96556884bf09fecdd7ccd530c87d1f7fdfee7f651fabc8bfcb6e086c278b77a7d3500000000000000000000000000 " ); use snowbridge_core::ParaId; #[test] -fn test_submit() { - new_tester::(OUTBOUND_QUEUE_ADDRESS.into()).execute_with(|| { +fn test_submit_happy_path() { + new_tester(GATEWAY_ADDRESS.into()).execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); @@ -238,15 +232,15 @@ fn test_submit() { dest: dest_para, nonce: 1, // dummy xcm sender doesn't actually send messages - result: MessageDispatchResult::InvalidPayload, + result: MessageDispatchResult::NotDispatched(SendError::NotApplicable), } .into()]); }); } #[test] -fn test_submit_with_invalid_outbound_queue() { - new_tester::(H160::zero()).execute_with(|| { +fn test_submit_with_invalid_gateway() { + new_tester(H160::zero()).execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); @@ -266,14 +260,14 @@ fn test_submit_with_invalid_outbound_queue() { }; assert_noop!( InboundQueue::submit(origin.clone(), message.clone()), - Error::::InvalidOutboundQueue + Error::::InvalidGateway ); }); } #[test] fn test_submit_with_invalid_nonce() { - new_tester::(OUTBOUND_QUEUE_ADDRESS.into()).execute_with(|| { + new_tester(GATEWAY_ADDRESS.into()).execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); @@ -307,7 +301,7 @@ fn test_submit_with_invalid_nonce() { #[test] fn test_submit_no_funds_to_reward_relayers() { - new_tester::(OUTBOUND_QUEUE_ADDRESS.into()).execute_with(|| { + new_tester(GATEWAY_ADDRESS.into()).execute_with(|| { let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); @@ -335,119 +329,29 @@ fn test_submit_no_funds_to_reward_relayers() { } #[test] -fn test_add_allow_list_without_root_yields_bad_origin() { - new_tester_with_config::(Default::default()).execute_with(|| { - let contract_address = hex!("0000000000000000000000000000000000000000").into(); - let relayer: AccountId = Keyring::Bob.into(); - let origin = RuntimeOrigin::signed(relayer); - assert_noop!( - InboundQueue::add_allow_list(origin, contract_address), - sp_runtime::DispatchError::BadOrigin, - ); - }); -} - -#[test] -fn test_add_allow_list_with_root_succeeds() { - new_tester_with_config::(Default::default()).execute_with(|| { - let origin = RuntimeOrigin::root(); - let contract_address = hex!("0000000000000000000000000000000000000000").into(); - - assert_eq!(>::get().len(), 0); - assert_ok!(InboundQueue::add_allow_list(origin, contract_address)); - - System::assert_last_event(RuntimeEvent::InboundQueue(crate::Event::AllowListAdded { - address: contract_address, - })); - - assert_eq!(>::get().len(), 1); - assert!(>::get().contains(&contract_address)); - }); -} - -#[test] -fn test_add_allow_list_ignores_duplicates() { - new_tester_with_config::(Default::default()).execute_with(|| { - let origin = RuntimeOrigin::root(); - let contract_address = hex!("0000000000000000000000000000000000000000").into(); - - assert_eq!(>::get().len(), 0); - assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address)); - assert_eq!(>::get().len(), 1); - assert!(>::get().contains(&contract_address)); - assert_ok!(InboundQueue::add_allow_list(origin, contract_address)); - assert_eq!(>::get().len(), 1); - assert!(>::get().contains(&contract_address)); - }); -} - -#[test] -fn test_add_allow_list_fails_when_exceeding_bounds() { - new_tester_with_config::(Default::default()).execute_with(|| { +fn test_set_gateway_with_root_succeeds() { + new_tester_with_config(Default::default()).execute_with(|| { let origin = RuntimeOrigin::root(); - let contract_address1 = hex!("0000000000000000000000000000000000000000").into(); - let contract_address2 = hex!("1000000000000000000000000000000000000000").into(); - let contract_address3 = hex!("3000000000000000000000000000000000000000").into(); - - assert_eq!(>::get().len(), 0); + let default_gateway_address = hex!("0000000000000000000000000000000000000000").into(); + let gateway_address = hex!("1000000000000000000000000000000000000000").into(); - assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address1)); - assert_eq!(>::get().len(), 1); + assert_eq!(>::get(), default_gateway_address); - assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address2)); - assert_eq!(>::get().len(), 2); + assert_ok!(InboundQueue::set_gateway(origin, gateway_address)); - assert_noop!( - InboundQueue::add_allow_list(origin, contract_address3), - Error::::AllowListFull, - ); - assert_eq!(>::get().len(), 2); + assert_eq!(>::get(), gateway_address); }); } #[test] -fn test_remove_allow_list_without_root_yields_bad_origin() { - new_tester_with_config::(Default::default()).execute_with(|| { - let contract_address = hex!("0000000000000000000000000000000000000000").into(); +fn test_set_gateway_without_root_yields_bad_origin() { + new_tester_with_config(Default::default()).execute_with(|| { + let gateway_address = hex!("0000000000000000000000000000000000000000").into(); let relayer: AccountId = Keyring::Bob.into(); let origin = RuntimeOrigin::signed(relayer); assert_noop!( - InboundQueue::remove_allow_list(origin, contract_address), + InboundQueue::set_gateway(origin, gateway_address), sp_runtime::DispatchError::BadOrigin, ); }); } - -#[test] -fn test_remove_allow_list_with_root_succeeds() { - new_tester_with_config::(Default::default()).execute_with(|| { - let origin = RuntimeOrigin::root(); - let contract_address = hex!("0000000000000000000000000000000000000000").into(); - - assert_eq!(>::get().len(), 0); - assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address)); - assert_eq!(>::get().len(), 1); - - assert_ok!(InboundQueue::remove_allow_list(origin, contract_address)); - System::assert_last_event(RuntimeEvent::InboundQueue(crate::Event::AllowListRemoved { - address: contract_address, - })); - - assert_eq!(>::get().len(), 0); - assert!(!>::get().contains(&contract_address)); - }); -} - -#[test] -fn test_remove_allow_list_event_not_emitted_for_none_existent_item() { - new_tester_with_config::(Default::default()).execute_with(|| { - let origin = RuntimeOrigin::root(); - let contract_address = hex!("0000000000000000000000000000000000000000").into(); - - let start = System::event_count(); - assert_ok!(InboundQueue::remove_allow_list(origin, contract_address)); - let end = System::event_count(); - - assert_eq!(start, end); // No new events - }); -} diff --git a/parachain/pallets/outbound-queue/src/benchmarking.rs b/parachain/pallets/outbound-queue/src/benchmarking.rs index e1830c56810d6..28f2c4615cbbc 100644 --- a/parachain/pallets/outbound-queue/src/benchmarking.rs +++ b/parachain/pallets/outbound-queue/src/benchmarking.rs @@ -4,6 +4,7 @@ use super::*; use codec::Encode; use frame_benchmarking::v2::*; +use snowbridge_core::outbound::Command; #[allow(unused_imports)] use crate::Pallet as OutboundQueue; @@ -17,16 +18,11 @@ mod benchmarks { /// Benchmark for processing a message payload of length `x`. #[benchmark] - fn do_process_message( - x: Linear<0, { T::MaxMessagePayloadSize::get() }>, - ) -> Result<(), BenchmarkError> { - let payload = (0..x).map(|_| 1u8).collect::>(); - + fn do_process_message() -> Result<(), BenchmarkError> { let enqueued_message = EnqueuedMessage { id: H256::zero().into(), origin: 1000.into(), - gateway: [1u8; 32].into(), - payload: payload.try_into().unwrap(), + command: Command::CreateAgent { agent_id: H256::zero() }, }; let encoded_enqueued_message = enqueued_message.encode(); diff --git a/parachain/pallets/outbound-queue/src/lib.rs b/parachain/pallets/outbound-queue/src/lib.rs index 2a134c4da0a7f..0fadae5ddf94f 100644 --- a/parachain/pallets/outbound-queue/src/lib.rs +++ b/parachain/pallets/outbound-queue/src/lib.rs @@ -1,7 +1,23 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -#![cfg_attr(not(feature = "std"), no_std)] +//! Pallet for committing outbound messages for delivery to Ethereum +//! +//! The message submission pipeline works like this: +//! 1. The message is first validated via [`OutboundQueue::validate`] +//! 2. The message is then enqueued for processing via [`OutboundQueue::submit`] +//! 3. The message queue is maintained by the external [`MessageQueue`] pallet +//! 4. [`MessageQueue`] delivers messages back to this pallet via `ProcessMessage::process_message` +//! 5. The message is processed in `do_process_message` +//! a. Assigned a nonce +//! b. ABI-encoded, hashed, and stored in the `Leaves` vector +//! 6. At the end of the block, a merkle root is constructed from all the leaves in `Leaves`. +//! 7. This merkle root is inserted into the parachain header as a digest item +//! +//! On the Ethereum side, the message root is ultimately the thing being +//! by the Polkadot light client. +//! +#![cfg_attr(not(feature = "std"), no_std)] pub mod api; pub mod weights; @@ -26,8 +42,8 @@ use sp_core::{RuntimeDebug, H256}; use sp_runtime::traits::Hash; use sp_std::prelude::*; -use snowbridge_core::{ - ContractId, OutboundMessage, OutboundQueue as OutboundQueueTrait, SubmitError, +use snowbridge_core::outbound::{ + Command, Message, MessageHash, OutboundQueue as OutboundQueueTrait, SubmitError, }; use snowbridge_outbound_queue_merkle_tree::merkle_root; @@ -42,39 +58,36 @@ pub enum AggregateMessageOrigin { } /// Message which is awaiting processing in the MessageQueue pallet -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, RuntimeDebug)] pub struct EnqueuedMessage { /// Message ID (usually hash of message) pub id: H256, /// ID of source parachain pub origin: ParaId, - /// The receiving gateway contract - pub gateway: ContractId, - /// Payload for target application. - pub payload: Vec, + /// Command to execute in the Gateway contract + pub command: Command, } /// Message which has been assigned a nonce and will be committed at the end of a block #[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)] -pub struct Message { +pub struct PreparedMessage { /// ID of source parachain origin: ParaId, /// Unique nonce to prevent replaying messages nonce: u64, - /// The receiving gateway contract - gateway: ContractId, - /// Payload for target application. - payload: Vec, + /// Command to execute in the Gateway contract + command: u8, + params: Vec, } /// Convert message into an ABI-encoded form for delivery to the InboundQueue contract on Ethereum -impl Into for Message { +impl Into for PreparedMessage { fn into(self) -> Token { Token::Tuple(vec![ Token::Uint(u32::from(self.origin).into()), Token::Uint(self.nonce.into()), - Token::FixedBytes(self.gateway.to_fixed_bytes().into()), - Token::Bytes(self.payload.to_vec()), + Token::Uint(self.command.into()), + Token::Bytes(self.params.to_vec()), ]) } } @@ -158,12 +171,12 @@ pub mod pallet { /// Messages to be committed in the current block. This storage value is killed in /// `on_initialize`, so should never go into block PoV. /// - /// Is never read in the runtime, only by offchain code. + /// Is never read in the runtime, only by offchain message relayers. /// /// Inspired by the `frame_system::Pallet::Events` storage value #[pallet::storage] #[pallet::unbounded] - pub(super) type Messages = StorageValue<_, Vec, ValueQuery>; + pub(super) type Messages = StorageValue<_, Vec, ValueQuery>; /// Hashes of the ABI-encoded messages in the [`Messages`] storage value. Used to generate a /// merkle root during `on_finalize`. This storage value is killed in @@ -195,15 +208,15 @@ pub mod pallet { where T::AccountId: AsRef<[u8]>, { - fn on_initialize(_: T::BlockNumber) -> Weight { + fn on_initialize(_: BlockNumberFor) -> Weight { // Remove storage from previous block Messages::::kill(); MessageLeaves::::kill(); // Reserve some weight for the `on_finalize` handler - return T::WeightInfo::on_finalize() + return T::WeightInfo::on_finalize(); } - fn on_finalize(_: T::BlockNumber) { + fn on_finalize(_: BlockNumberFor) { Self::commit_messages(); } } @@ -242,7 +255,7 @@ pub mod pallet { pub(crate) fn commit_messages() { let count = MessageLeaves::::decode_len().unwrap_or_default() as u64; if count == 0 { - return + return; } // Create merkle root of messages @@ -263,13 +276,18 @@ pub mod pallet { let next_nonce = Nonce::::get(enqueued_message.origin).saturating_add(1); - let message: Message = Message { + let (command, params) = enqueued_message.command.abi_encode(); + + // Construct a prepared message, which when ABI-encoded is what the + // other side of the bridge will verify. + let message: PreparedMessage = PreparedMessage { origin: enqueued_message.origin, nonce: next_nonce, - gateway: enqueued_message.gateway, - payload: enqueued_message.payload, + command, + params, }; + // ABI-encode and hash the prepared message let message_abi_encoded = ethabi::encode(&vec![message.clone().into()]); let message_abi_encoded_hash = ::Hashing::hash(&message_abi_encoded); @@ -297,17 +315,21 @@ pub mod pallet { impl OutboundQueueTrait for Pallet { type Ticket = OutboundQueueTicket>; - fn validate(message: &OutboundMessage) -> Result { + fn validate(message: &Message) -> Result { // The inner payload should not be too large + let (_, payload) = message.command.abi_encode(); + + // Create a message id for tracking progress in submission pipeline + let message_id: MessageHash = sp_io::hashing::blake2_256(&(message.encode())).into(); + ensure!( - message.payload.len() < T::MaxMessagePayloadSize::get() as usize, + payload.len() < T::MaxMessagePayloadSize::get() as usize, SubmitError::MessageTooLarge ); let message: EnqueuedMessage = EnqueuedMessage { - id: message.id, + id: message_id, origin: message.origin, - gateway: message.gateway, - payload: message.payload.clone().into(), + command: message.command.clone(), }; // The whole message should not be too large let encoded = message.encode().try_into().map_err(|_| SubmitError::MessageTooLarge)?; @@ -317,14 +339,14 @@ pub mod pallet { Ok(ticket) } - fn submit(ticket: Self::Ticket) -> Result<(), SubmitError> { + fn submit(ticket: Self::Ticket) -> Result { Self::ensure_not_halted().map_err(|_| SubmitError::BridgeHalted)?; T::MessageQueue::enqueue_message( ticket.message.as_bounded_slice(), AggregateMessageOrigin::Parachain(ticket.origin), ); Self::deposit_event(Event::MessageQueued { id: ticket.id }); - Ok(()) + Ok(ticket.id) } } @@ -339,14 +361,14 @@ pub mod pallet { // Yield if we don't want to accept any more messages in the current block. // There is hard limit to ensure the weight of `on_finalize` is bounded. ensure!( - MessageLeaves::::decode_len().unwrap_or(0) < - T::MaxMessagesPerBlock::get() as usize, + MessageLeaves::::decode_len().unwrap_or(0) + < T::MaxMessagesPerBlock::get() as usize, ProcessMessageError::Yield ); let weight = T::WeightInfo::do_process_message(); if !meter.check_accrue(weight) { - return Err(ProcessMessageError::Overweight(weight)) + return Err(ProcessMessageError::Overweight(weight)); } Self::do_process_message(message) diff --git a/parachain/pallets/outbound-queue/src/test.rs b/parachain/pallets/outbound-queue/src/test.rs index 368082377c944..6a268fa421f55 100644 --- a/parachain/pallets/outbound-queue/src/test.rs +++ b/parachain/pallets/outbound-queue/src/test.rs @@ -8,7 +8,7 @@ use frame_support::{ weights::WeightMeter, }; -use sp_core::H256; +use sp_core::{H160, H256}; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Keccak256, Verify}, @@ -83,7 +83,7 @@ impl pallet_message_queue::Config for Test { } parameter_types! { - pub const MaxMessagePayloadSize: u32 = 256; + pub const MaxMessagePayloadSize: u32 = 1024; pub const MaxMessagesPerBlock: u32 = 20; } @@ -125,11 +125,13 @@ fn submit_messages_from_multiple_origins_and_commit() { //next_block(); for para_id in 1000..1004 { - let message = OutboundMessage { - id: H256::repeat_byte(1).into(), + let message = Message { origin: para_id.into(), - gateway: [1u8; 32].into(), - payload: (0..100).map(|_| 1u8).collect::>(), + command: Command::Upgrade { + impl_address: H160::zero(), + impl_code_hash: H256::zero(), + params: Some((0..100).map(|_| 1u8).collect::>()), + }, }; let result = OutboundQueue::validate(&message); @@ -156,11 +158,13 @@ fn submit_messages_from_multiple_origins_and_commit() { #[test] fn submit_message_fail_too_large() { new_tester().execute_with(|| { - let message = OutboundMessage { - id: H256::repeat_byte(1).into(), + let message = Message { origin: 1000.into(), - gateway: [1u8; 32].into(), - payload: (0..1000).map(|_| 1u8).collect::>(), + command: Command::Upgrade { + impl_address: H160::zero(), + impl_code_hash: H256::zero(), + params: Some((0..1000).map(|_| 1u8).collect::>()), + }, }; assert_err!(OutboundQueue::validate(&message), SubmitError::MessageTooLarge); diff --git a/parachain/primitives/core/Cargo.toml b/parachain/primitives/core/Cargo.toml index 533285e5c387d..466655f14f77c 100644 --- a/parachain/primitives/core/Cargo.toml +++ b/parachain/primitives/core/Cargo.toml @@ -20,6 +20,9 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } snowbridge-beacon-primitives = { path = "../../primitives/beacon", default-features = false } +ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } + + [dev-dependencies] hex = { package = "rustc-hex", version = "2.1.0", default-features = false } @@ -37,6 +40,7 @@ std = [ "sp-runtime/std", "snowbridge-ethereum/std", "snowbridge-beacon-primitives/std", - "xcm/std" + "xcm/std", + "ethabi/std" ] runtime-benchmarks = [] diff --git a/parachain/primitives/core/src/types.rs b/parachain/primitives/core/src/inbound.rs similarity index 58% rename from parachain/primitives/core/src/types.rs rename to parachain/primitives/core/src/inbound.rs index 34c6dab56ba7b..5527802099e36 100644 --- a/parachain/primitives/core/src/types.rs +++ b/parachain/primitives/core/src/inbound.rs @@ -1,23 +1,20 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -//! Types for representing messages +//! Types for representing inbound messages use codec::{Decode, Encode}; +use frame_support::dispatch::DispatchError; use frame_support::{scale_info::TypeInfo, RuntimeDebug}; -use sp_core::{H160, H256}; -use sp_runtime::DigestItem; +use snowbridge_ethereum::Log; +use sp_core::H256; use sp_std::vec::Vec; -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] -pub struct MessageId { - account: H160, - nonce: u64, -} - -impl MessageId { - pub fn new(account: H160, nonce: u64) -> MessageId { - MessageId { account, nonce } - } +/// A trait for verifying inbound messages from Ethereum. +/// +/// This trait should be implemented by runtime modules that wish to provide message verification +/// functionality. +pub trait Verifier { + fn verify(message: &Message) -> Result; } pub type MessageNonce = u64; @@ -41,19 +38,6 @@ pub struct Proof { pub block_hash: H256, // The index of the transaction (and receipt) within the block. pub tx_index: u32, - // Proof keys and values + // Proof keys and values (receipts tree) pub data: (Vec>, Vec>), } - -/// Auxiliary [`DigestItem`] to include in header digest. -#[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)] -pub enum AuxiliaryDigestItem { - /// A batch of messages has been committed. - Commitment(H256), -} - -impl Into for AuxiliaryDigestItem { - fn into(self) -> DigestItem { - DigestItem::Other(self.encode()) - } -} diff --git a/parachain/primitives/core/src/lib.rs b/parachain/primitives/core/src/lib.rs index 9dd47d54219aa..01539e6d3e8b9 100644 --- a/parachain/primitives/core/src/lib.rs +++ b/parachain/primitives/core/src/lib.rs @@ -8,98 +8,13 @@ #![allow(unused_variables)] #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode}; -use frame_support::dispatch::DispatchError; -use scale_info::TypeInfo; -use snowbridge_ethereum::Log; -use sp_core::{RuntimeDebug, H256}; -use sp_std::vec::Vec; - +pub mod inbound; +pub mod outbound; pub mod ringbuffer; -pub mod types; pub use polkadot_parachain::primitives::Id as ParaId; pub use ringbuffer::{RingBufferMap, RingBufferMapImpl}; -pub use types::{Message, MessageId, MessageNonce, Proof}; - -/// A stable id for a bridge contract on the Ethereum side -#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, TypeInfo, RuntimeDebug)] -pub struct ContractId([u8; 32]); - -impl From<[u8; 32]> for ContractId { - fn from(value: [u8; 32]) -> Self { - Self(value) - } -} - -impl From for ContractId { - fn from(value: H256) -> Self { - Self(value.to_fixed_bytes()) - } -} - -impl ContractId { - pub fn to_fixed_bytes(self) -> [u8; 32] { - self.0 - } - pub fn as_fixed_bytes(&self) -> &[u8; 32] { - &self.0 - } -} - -impl ContractId { - pub const fn new(id: [u8; 32]) -> Self { - Self(id) - } -} - -/// A trait for verifying messages. -/// -/// This trait should be implemented by runtime modules that wish to provide message verification -/// functionality. -pub trait Verifier { - fn verify(message: &Message) -> Result; -} - -#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug)] -pub enum SubmitError { - MessageTooLarge, - BridgeHalted, -} - -/// A message which can be accepted by the [`OutboundQueue`] -#[derive(Clone, RuntimeDebug)] -pub struct OutboundMessage { - /// A unique ID to identify a message while its in the processing queue. Usually the Xcm - /// message hash. - pub id: H256, - /// The parachain from which the message originated - pub origin: ParaId, - /// The stable ID for a receiving gateway contract - pub gateway: ContractId, - /// ABI-encoded message payload which can be interpreted by the receiving gateway contract - pub payload: Vec, -} - -// A trait for enqueueing messages for delivery to Ethereum -pub trait OutboundQueue { - type Ticket; - - /// Validate a message destined for Ethereum - fn validate(message: &OutboundMessage) -> Result; - - /// Submit the message for eventual delivery to Ethereum - fn submit(ticket: Self::Ticket) -> Result<(), SubmitError>; -} - -impl OutboundQueue for () { - type Ticket = u64; - - fn validate(message: &OutboundMessage) -> Result { - Ok(0) - } +use sp_core::H256; - fn submit(ticket: Self::Ticket) -> Result<(), SubmitError> { - Ok(()) - } -} +/// The ID of an agent contract +pub type AgentId = H256; diff --git a/parachain/primitives/core/src/outbound.rs b/parachain/primitives/core/src/outbound.rs new file mode 100644 index 0000000000000..752548bf7d4e7 --- /dev/null +++ b/parachain/primitives/core/src/outbound.rs @@ -0,0 +1,231 @@ +use codec::{Decode, Encode}; +pub use polkadot_parachain::primitives::Id as ParaId; +use sp_core::{RuntimeDebug, H160, H256, U256}; +use sp_std::{borrow::ToOwned, vec, vec::Vec}; + +pub type MessageHash = H256; + +/// A trait for enqueueing messages for delivery to Ethereum +pub trait OutboundQueue { + type Ticket; + + /// Validate a message + fn validate(message: &Message) -> Result; + + /// Submit the message ticket for eventual delivery to Ethereum + fn submit(ticket: Self::Ticket) -> Result; +} + +/// Default implementation of `OutboundQueue` for tests +impl OutboundQueue for () { + type Ticket = u64; + + fn validate(message: &Message) -> Result { + Ok(0) + } + + fn submit(ticket: Self::Ticket) -> Result { + Ok(MessageHash::zero()) + } +} + +/// Errors returned by the [`OutboundQueue`] +#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug)] +pub enum SubmitError { + /// Message is too large to be safely executed on Ethereum + MessageTooLarge, + /// The bridge has been halted for maintenance + BridgeHalted, +} + +/// A message which can be accepted by the [`OutboundQueue`] +#[derive(Clone, Encode, Decode, RuntimeDebug)] +pub struct Message { + /// The parachain from which the message originated + pub origin: ParaId, + /// The stable ID for a receiving gateway contract + pub command: Command, +} + +use ethabi::Token; + +#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug)] +pub enum OperatingMode { + Normal, + RejectingOutboundMessages, +} + +/// A command which is executable by the Gateway contract on Ethereum +#[derive(Clone, Encode, Decode, RuntimeDebug)] +pub enum Command { + /// Execute a sub-command within an agent for a consensus system in Polkadot + AgentExecute { + /// The ID of the agent + agent_id: H256, + /// The sub-command to be executed + command: AgentExecuteCommand, + }, + /// Upgrade the Gateway contract + Upgrade { + /// Address of the new implementation contract + impl_address: H160, + /// Codehash of the implementation contract + impl_code_hash: H256, + /// Optional list of parameters to pass to initializer in the implementation contract + params: Option>, + }, + /// Create an agent representing a consensus system on Polkadot + CreateAgent { + /// The ID of the agent, derived from the `MultiLocation` of the consensus system on Polkadot + agent_id: H256, + }, + /// Create bidirectional messaging channel to a parachain + CreateChannel { + /// The ID of the parachain + para_id: ParaId, + /// The agent ID of the parachain + agent_id: H256, + }, + /// Update the configuration of a channel + UpdateChannel { + /// The ID of the parachain to which the channel belongs. + para_id: ParaId, + /// The new operating mode + mode: OperatingMode, + /// The new fee to charge users for outbound messaging to Polkadot + fee: u128, + /// The new reward to give to relayers for submitting inbound messages from Polkadot + reward: u128, + }, + /// Set the global operating mode of the Gateway contract + SetOperatingMode { + /// The new operating mode + mode: OperatingMode, + }, + /// Transfer ether from an agent + TransferNativeFromAgent { + /// The agent ID + agent_id: H256, + /// The recipient of the ether + recipient: H160, + /// The amount to transfer + amount: u128, + }, +} + +impl Command { + /// Compute the enum variant index + pub fn index(&self) -> u8 { + match self { + Command::AgentExecute { .. } => 0, + Command::Upgrade { .. } => 1, + Command::CreateAgent { .. } => 2, + Command::CreateChannel { .. } => 3, + Command::UpdateChannel { .. } => 4, + Command::SetOperatingMode { .. } => 5, + Command::TransferNativeFromAgent { .. } => 6, + } + } + + /// ABI-encode the Command. + /// Returns a tuple of: + /// - Index of the command + /// - the ABI encoded command + pub fn abi_encode(&self) -> (u8, Vec) { + match self { + Command::AgentExecute { agent_id, command } => ( + self.index(), + ethabi::encode(&vec![Token::Tuple(vec![ + Token::FixedBytes(agent_id.as_bytes().to_owned()), + Token::Bytes(command.abi_encode()), + ])]), + ), + Command::Upgrade { impl_address, impl_code_hash, params } => ( + self.index(), + ethabi::encode(&vec![Token::Tuple(vec![ + Token::Address(*impl_address), + Token::FixedBytes(impl_code_hash.as_bytes().to_owned()), + params.clone().map_or(Token::Bytes(vec![]), |p| Token::Bytes(p)), + ])]), + ), + Command::CreateAgent { agent_id } => ( + self.index(), + ethabi::encode(&vec![Token::Tuple(vec![Token::FixedBytes( + agent_id.as_bytes().to_owned(), + )])]), + ), + Command::CreateChannel { para_id, agent_id } => { + let para_id: u32 = (*para_id).into(); + ( + self.index(), + ethabi::encode(&vec![Token::Tuple(vec![ + Token::Uint(U256::from(para_id)), + Token::FixedBytes(agent_id.as_bytes().to_owned()), + ])]), + ) + }, + Command::UpdateChannel { para_id, mode, fee, reward } => { + let para_id: u32 = (*para_id).into(); + ( + self.index(), + ethabi::encode(&vec![Token::Tuple(vec![ + Token::Uint(U256::from(para_id)), + Token::Uint(U256::from((*mode) as u64)), + Token::Uint(U256::from(*fee)), + Token::Uint(U256::from(*reward)), + ])]), + ) + }, + Command::SetOperatingMode { mode } => ( + self.clone().index(), + ethabi::encode(&vec![Token::Tuple(vec![Token::Uint(U256::from((*mode) as u64))])]), + ), + Command::TransferNativeFromAgent { agent_id, recipient, amount } => ( + self.clone().index(), + ethabi::encode(&vec![Token::Tuple(vec![ + Token::FixedBytes(agent_id.as_bytes().to_owned()), + Token::Address(*recipient), + Token::Uint(U256::from(*amount)), + ])]), + ), + } + } +} + +/// A Sub-command executable within an agent +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)] +pub enum AgentExecuteCommand { + /// Transfer ERC20 tokens + TransferToken { + /// Address of the ERC20 token + token: H160, + /// The recipient of the tokens + recipient: H160, + /// The amount of tokens to transfer + amount: u128, + }, +} + +impl AgentExecuteCommand { + fn index(&self) -> u8 { + match self { + AgentExecuteCommand::TransferToken { .. } => 0, + } + } + + /// ABI-encode the sub-command + pub fn abi_encode(&self) -> Vec { + match self { + AgentExecuteCommand::TransferToken { token, recipient, amount } => { + ethabi::encode(&vec![ + Token::Uint(self.index().into()), + Token::Bytes(ethabi::encode(&vec![ + Token::Address(*token), + Token::Address(*recipient), + Token::Uint(U256::from(*amount)), + ])), + ]) + }, + } + } +} diff --git a/parachain/primitives/ethereum/Cargo.toml b/parachain/primitives/ethereum/Cargo.toml index dbc289051838a..b0bcfffdc317e 100644 --- a/parachain/primitives/ethereum/Cargo.toml +++ b/parachain/primitives/ethereum/Cargo.toml @@ -26,7 +26,6 @@ ethabi = { git = "https://github.com/snowfork/ethabi-decode.git", package = "eth [dev-dependencies] wasm-bindgen-test = "0.3.19" -snowbridge-testutils = { path = "../../primitives/testutils" } rand = "0.8.5" serde = { version = "1.0.164", features = [ "derive" ] } serde_json = "1.0.96" diff --git a/parachain/primitives/router/Cargo.toml b/parachain/primitives/router/Cargo.toml index 6d54a747dfc51..2fe1bbf22e170 100644 --- a/parachain/primitives/router/Cargo.toml +++ b/parachain/primitives/router/Cargo.toml @@ -17,6 +17,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "ma sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } xcm = { git = "https://github.com/paritytech/polkadot.git", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot.git", branch = "master", default-features = false } xcm-executor = { git = "https://github.com/paritytech/polkadot.git", branch = "master", default-features = false } snowbridge-core = { path = "../../primitives/core", default-features = false } @@ -41,6 +42,7 @@ std = [ "sp-runtime/std", "sp-std/std", "xcm/std", + "xcm-builder/std", "xcm-executor/std", "snowbridge-core/std", "ethabi/std", diff --git a/parachain/primitives/router/src/inbound/mod.rs b/parachain/primitives/router/src/inbound/mod.rs index c653859488c89..f610d31a755b0 100644 --- a/parachain/primitives/router/src/inbound/mod.rs +++ b/parachain/primitives/router/src/inbound/mod.rs @@ -26,89 +26,49 @@ pub enum VersionedMessage { pub struct MessageV1 { /// EIP-155 chain id of the origin Ethereum network pub chain_id: u64, - /// The gateway-specific message - pub message: GatewayMessage, + /// The command + pub message: Command, } #[derive(Clone, Encode, Decode, RuntimeDebug)] -pub enum GatewayMessage { - UpgradeProxy(UpgradeProxyMessage), - NativeTokens(NativeTokensMessage), +pub enum Command { + RegisterToken { gateway: H160, token: H160, create_call_index: [u8; 2] }, + SendToken { gateway: H160, token: H160, destination: Destination, amount: u128 }, } #[derive(Clone, Encode, Decode, RuntimeDebug)] -pub enum UpgradeProxyMessage {} - -#[derive(Clone, Encode, Decode, RuntimeDebug)] -pub enum NativeTokensMessage { - Create { - origin: H160, - token: H160, - name: Vec, - symbol: Vec, - decimals: u8, - create_call_index: [u8; 2], - set_metadata_call_index: [u8; 2], - }, - Mint { - origin: H160, - token: H160, - dest: Option, - recipient: MultiLocation, // Recipient of funds on final destination - amount: u128, - }, -} - -pub enum ConvertError { - /// Message is in the wrong format - BadFormat, +pub enum Destination { + AccountId32 { id: [u8; 32] }, + ForeignAccountId32 { para_id: u32, id: [u8; 32] }, + ForeignAccountId20 { para_id: u32, id: [u8; 20] }, } -impl TryInto> for MessageV1 { - type Error = ConvertError; - - fn try_into(self) -> Result, Self::Error> { - match self.message { - GatewayMessage::UpgradeProxy(message) => message.convert(self.chain_id), - GatewayMessage::NativeTokens(message) => message.convert(self.chain_id), - } +impl Into> for MessageV1 { + fn into(self) -> Xcm<()> { + self.message.convert(self.chain_id) } } -impl UpgradeProxyMessage { - pub fn convert(self, _chain_id: u64) -> Result, ConvertError> { - // The UpgradeProxy gateway doesn't send any messages to Polkadot - Err(ConvertError::BadFormat) - } -} - -impl NativeTokensMessage { - pub fn convert(self, chain_id: u64) -> Result, ConvertError> { +impl Command { + pub fn convert(self, chain_id: u64) -> Xcm<()> { let network = NetworkId::Ethereum { chain_id }; - let buy_execution_fee_amount = 2_000_000_000; //TODO: WeightToFee::weight_to_fee(&Weight::from_parts(100_000_000, 18_000)); + // TODO: WeightToFee::weight_to_fee(&Weight::from_parts(100_000_000, 18_000)); + let buy_execution_fee_amount = 2_000_000_000; let buy_execution_fee = MultiAsset { id: Concrete(MultiLocation::parent()), fun: Fungible(buy_execution_fee_amount), }; match self { - NativeTokensMessage::Create { - origin, - token, - name, - symbol, - decimals, - create_call_index, - set_metadata_call_index, - } => { + Command::RegisterToken { gateway, token, create_call_index } => { let owner = GlobalConsensusEthereumAccountConvertsFor::<[u8; 32]>::from_params( &chain_id, - origin.as_fixed_bytes(), + gateway.as_fixed_bytes(), ); - let origin_location = Junction::AccountKey20 { network: None, key: origin.into() }; + let origin_location = Junction::AccountKey20 { network: None, key: gateway.into() }; - let asset_id = Self::convert_token_address(network, origin, token); + let asset_id = Self::convert_token_address(network, gateway, token); let instructions: Vec> = vec![ UniversalOrigin(GlobalConsensus(network)), DescendOrigin(X1(origin_location)), @@ -143,22 +103,16 @@ impl NativeTokensMessage { .into(), }, ExpectTransactStatus(MaybeErrorCode::Success), - Transact { - origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(200_000_000, 8_000), - call: (set_metadata_call_index, asset_id, name, symbol, decimals) - .encode() - .into(), - }, - ExpectTransactStatus(MaybeErrorCode::Success), ]; - Ok(instructions.into()) + instructions.into() }, - NativeTokensMessage::Mint { origin, token, dest, recipient, amount } => { - let asset = - MultiAsset::from((Self::convert_token_address(network, origin, token), amount)); + Command::SendToken { gateway, token, destination, amount } => { + let asset = MultiAsset::from(( + Self::convert_token_address(network, gateway, token), + amount, + )); - let origin_location = Junction::AccountKey20 { network: None, key: origin.into() }; + let origin_location = Junction::AccountKey20 { network: None, key: gateway.into() }; let mut instructions: Vec> = vec![ UniversalOrigin(GlobalConsensus(network)), @@ -185,28 +139,49 @@ impl NativeTokensMessage { ClearOrigin, ]; - match dest { - Some(para) => { - let mut fragment: Vec> = vec![DepositReserveAsset { - assets: MultiAssetFilter::Definite(vec![asset.clone()].into()), - dest: MultiLocation { parents: 1, interior: X1(Parachain(para)) }, - xcm: vec![DepositAsset { - assets: MultiAssetFilter::Definite(vec![asset.clone()].into()), - beneficiary: recipient, - }] - .into(), - }]; - instructions.append(&mut fragment); + let (dest_para_id, beneficiary) = match destination { + Destination::AccountId32 { id } => ( + None, + MultiLocation { + parents: 0, + interior: X1(AccountId32 { network: None, id }), + }, + ), + Destination::ForeignAccountId32 { para_id, id } => ( + Some(para_id), + MultiLocation { + parents: 0, + interior: X1(AccountId32 { network: None, id }), + }, + ), + Destination::ForeignAccountId20 { para_id, id } => ( + Some(para_id), + MultiLocation { + parents: 0, + interior: X1(AccountKey20 { network: None, key: id }), + }, + ), + }; + + let assets = MultiAssetFilter::Definite(vec![asset.clone()].into()); + + let mut fragment: Vec> = match dest_para_id { + Some(dest_para_id) => { + vec![DepositReserveAsset { + assets: assets.clone(), + dest: MultiLocation { + parents: 1, + interior: X1(Parachain(dest_para_id.into())), + }, + xcm: vec![DepositAsset { assets: assets.clone(), beneficiary }].into(), + }] }, None => { - let mut fragment: Vec> = vec![DepositAsset { - assets: MultiAssetFilter::Definite(vec![asset.clone()].into()), - beneficiary: recipient, - }]; - instructions.append(&mut fragment); + vec![DepositAsset { assets, beneficiary }] }, - } - Ok(instructions.into()) + }; + instructions.append(&mut fragment); + instructions.into() }, } } @@ -268,13 +243,13 @@ mod tests { use xcm::v3::prelude::*; use xcm_executor::traits::ConvertLocation; - const CONTRACT_ADDRESS: [u8; 20] = hex!("D184c103F7acc340847eEE82a0B909E3358bc28d"); + const CONTRACT_ADDRESS: [u8; 20] = hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); const NETWORK: NetworkId = Ethereum { chain_id: 15 }; const SS58_FORMAT: u16 = 2; const EXPECTED_SOVEREIGN_KEY: [u8; 32] = - hex!("5d6987649e0dac78ddf852eb0f1b1d1bf2be9623d81cb16c17cfa145948bb6dc"); + hex!("c9794dd8013efb2ad83f668845c62b373c16ad33971745731408058e4d0c6ff5"); const EXPECTED_SOVEREIGN_ADDRESS: &'static str = - "EgoKVgdhGVz41LyP2jckLrmXjnD35xitaX221ktZjQ2Xsxw"; + "H8VBFC4LG91ByxMG6GwsCcAacjitnzGmGbqnvSEQFBywJEL"; parameter_types! { pub EthereumNetwork: NetworkId = NETWORK; @@ -297,10 +272,11 @@ mod tests { .unwrap(); let address = frame_support::sp_runtime::AccountId32::new(account) .to_ss58check_with_version(SS58_FORMAT.into()); - assert_eq!(account, EXPECTED_SOVEREIGN_KEY); - assert_eq!(address, EXPECTED_SOVEREIGN_ADDRESS); println!("SS58: {}\nBytes: {:?}", address, account); + + assert_eq!(account, EXPECTED_SOVEREIGN_KEY); + assert_eq!(address, EXPECTED_SOVEREIGN_ADDRESS); } #[test] diff --git a/parachain/primitives/router/src/outbound/mod.rs b/parachain/primitives/router/src/outbound/mod.rs index 3cc46ce05b926..a9bf6cb7c6de8 100644 --- a/parachain/primitives/router/src/outbound/mod.rs +++ b/parachain/primitives/router/src/outbound/mod.rs @@ -1,33 +1,38 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -pub mod payload; - use core::slice::Iter; use codec::{Decode, Encode}; use frame_support::{ensure, log, traits::Get}; -use snowbridge_core::{OutboundMessage, OutboundQueue as OutboundQueueTrait}; +use snowbridge_core::outbound::{ + AgentExecuteCommand, Command, Message, OutboundQueue as OutboundQueueTrait, +}; use sp_core::{H160, H256}; use sp_std::{marker::PhantomData, prelude::*}; use xcm::v3::prelude::*; -use xcm_executor::traits::ExportXcm; +use xcm_builder::{DescribeAllTerminal, DescribeFamily, HashedDescription}; +use xcm_executor::traits::{ConvertLocation, ExportXcm}; -use payload::{Message, NativeTokensMessage}; +pub type AgentHashedDescription = HashedDescription>; -pub struct EthereumBlobExporter( - PhantomData<(UniversalLocation, BridgeLocation, OutboundQueue)>, -); +pub struct EthereumBlobExporter< + UniversalLocation, + BridgeLocation, + OutboundQueue, + AgentHashedDescription, +>(PhantomData<(UniversalLocation, BridgeLocation, OutboundQueue, AgentHashedDescription)>); -impl ExportXcm - for EthereumBlobExporter +impl ExportXcm + for EthereumBlobExporter where UniversalLocation: Get, BridgeLocation: Get, OutboundQueue: OutboundQueueTrait, OutboundQueue::Ticket: Encode + Decode, + AgentHashedDescription: ConvertLocation, { - type Ticket = (Vec, XcmHash); + type Ticket = Vec; fn validate( network: NetworkId, @@ -47,22 +52,24 @@ where if network != bridge_network { log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched bridge network {network:?}."); - return Err(SendError::NotApplicable) + return Err(SendError::NotApplicable); } let dest = destination.take().ok_or(SendError::MissingArgument)?; if dest != Here { log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched remote destination {dest:?}."); - return Err(SendError::NotApplicable) + return Err(SendError::NotApplicable); } let registry_contract = match registry_location { X1(AccountKey20 { network, key }) if network.is_none() || network == Some(bridge_network) => - key, + { + key + }, _ => { log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched registry contract {registry_location:?}."); - return Err(SendError::NotApplicable) + return Err(SendError::NotApplicable); }, }; @@ -80,14 +87,14 @@ where if Ok(local_net) != universal_location.global_consensus() { log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched relay network {local_net:?}."); - return Err(SendError::NotApplicable) + return Err(SendError::NotApplicable); } let para_id = match local_sub { X1(Parachain(para_id)) => para_id, _ => { log::error!(target: "xcm::ethereum_blob_exporter", "could not get parachain id from universal source '{local_sub:?}'."); - return Err(SendError::MissingArgument) + return Err(SendError::MissingArgument); }, }; @@ -97,49 +104,56 @@ where })?; let mut converter = XcmConverter::new(&message, &bridge_network, ®istry_contract); - let (converted_message, max_target_fee) = converter.convert().map_err(|err|{ + let (agent_execute_command, max_target_fee) = converter.convert().map_err(|err|{ log::error!(target: "xcm::ethereum_blob_exporter", "unroutable due to pattern matching error '{err:?}'."); SendError::Unroutable })?; if max_target_fee.is_some() { log::error!(target: "xcm::ethereum_blob_exporter", "unroutable due not supporting max target fee."); - return Err(SendError::Unroutable) + return Err(SendError::Unroutable); } - let (gateway, payload) = converted_message.encode(); - - let hash_input = (para_id, gateway, payload.clone()).encode(); - let message_id: H256 = sp_io::hashing::blake2_256(&hash_input).into(); + // local_sub is relative to the relaychain. No conversion needed. + let local_sub_location: MultiLocation = local_sub.into(); + let agent_id = match AgentHashedDescription::convert_location(&local_sub_location) { + Some(id) => id, + None => { + log::error!(target: "xcm::ethereum_blob_exporter", "unroutable due to not being able to create agent id. '{local_sub_location:?}'"); + return Err(SendError::Unroutable); + }, + }; - let outbound_message = - OutboundMessage { id: message_id, origin: para_id.into(), gateway, payload }; + let outbound_message = Message { + origin: para_id.into(), + command: Command::AgentExecute { agent_id, command: agent_execute_command }, + }; - let ticket = OutboundQueue::validate(&outbound_message).map_err(|_| { - log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue validation of message failed"); + let ticket = OutboundQueue::validate(&outbound_message).map_err(|err| { + log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue validation of message failed. {err:?}"); SendError::Unroutable })?; - log::info!(target: "xcm::ethereum_blob_exporter", "message validated {message_id:#?}."); + log::info!(target: "xcm::ethereum_blob_exporter", "message validated: location = {local_sub_location:?}, agent_id = '{agent_id:?}'"); // TODO: Fees if any currently returning empty multi assets as cost - Ok(((ticket.encode(), message_id.into()), MultiAssets::default())) + Ok((ticket.encode(), MultiAssets::default())) } - fn deliver((blob, hash): (Vec, XcmHash)) -> Result { + fn deliver(blob: Vec) -> Result { let ticket: OutboundQueue::Ticket = OutboundQueue::Ticket::decode(&mut blob.as_ref()) .map_err(|_| { log::trace!(target: "xcm::ethereum_blob_exporter", "undeliverable due to decoding error"); SendError::NotApplicable })?; - OutboundQueue::submit(ticket).map_err(|_| { + let message_hash = OutboundQueue::submit(ticket).map_err(|_| { log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue submit of message failed"); SendError::Transport("other transport error") })?; - log::info!(target: "xcm::ethereum_blob_exporter", "message delivered {hash:#?}."); - Ok(hash) + log::info!(target: "xcm::ethereum_blob_exporter", "message delivered {message_hash:#?}."); + Ok(message_hash.into()) } } @@ -176,7 +190,9 @@ impl<'a, Call> XcmConverter<'a, Call> { Self { iter: message.inner().iter(), bridged_location, registry_contract } } - fn convert(&mut self) -> Result<(Message, Option<&'a MultiAsset>), XcmConverterError> { + fn convert( + &mut self, + ) -> Result<(AgentExecuteCommand, Option<&'a MultiAsset>), XcmConverterError> { // Get target fees if specified. let max_target_fee = self.fee_info()?; @@ -191,7 +207,7 @@ impl<'a, Call> XcmConverter<'a, Call> { // All xcm instructions must be consumed before exit. if self.next().is_ok() { - return Err(XcmConverterError::EndOfXcmMessageExpected) + return Err(XcmConverterError::EndOfXcmMessageExpected); } Ok((result, max_target_fee)) @@ -203,7 +219,9 @@ impl<'a, Call> XcmConverter<'a, Call> { WithdrawAsset(fee_asset) => match self.next()? { BuyExecution { fees: execution_fee, weight_limit: Unlimited } if fee_asset.len() == 1 && fee_asset.contains(&execution_fee) => - Some(execution_fee), + { + Some(execution_fee) + }, _ => return Err(BuyExecutionExpected), }, UnpaidExecution { check_origin: None, weight_limit: Unlimited } => None, @@ -212,22 +230,24 @@ impl<'a, Call> XcmConverter<'a, Call> { Ok(execution_fee) } - fn to_native_tokens_unlock_message(&mut self) -> Result { + fn to_native_tokens_unlock_message( + &mut self, + ) -> Result { use XcmConverterError::*; let (assets, beneficiary) = if let WithdrawAsset(reserved_assets) = self.next()? { if reserved_assets.len() == 0 { - return Err(NoReserveAssets) + return Err(NoReserveAssets); } if let DepositAsset { assets, beneficiary } = self.next()? { if reserved_assets.inner().iter().any(|asset| !assets.matches(asset)) { - return Err(FilterDoesNotConsumeAllAssets) + return Err(FilterDoesNotConsumeAllAssets); } (reserved_assets, beneficiary) } else { - return Err(DepositExpected) + return Err(DepositExpected); } } else { - return Err(WithdrawExpected) + return Err(WithdrawExpected); }; // assert that the benificiary is ethereum account key 20 @@ -236,11 +256,11 @@ impl<'a, Call> XcmConverter<'a, Call> { beneficiary { if network.is_some() && network != &Some(*self.bridged_location) { - return Err(BeneficiaryResolutionFailed) + return Err(BeneficiaryResolutionFailed); } H160(*key) } else { - return Err(BeneficiaryResolutionFailed) + return Err(BeneficiaryResolutionFailed); } }; @@ -254,7 +274,7 @@ impl<'a, Call> XcmConverter<'a, Call> { if let MultiAsset { id: Concrete(location), fun: Fungible(amount) } = asset { (location, amount) } else { - return Err(AssetNotConcreteFungible) + return Err(AssetNotConcreteFungible); }; ensure!(*amount > 0, ZeroAssetTransfer); @@ -270,21 +290,21 @@ impl<'a, Call> XcmConverter<'a, Call> { } = asset_location { if registry_network.is_some() && registry_network != &Some(*self.bridged_location) { - return Err(AssetResolutionFailed) + return Err(AssetResolutionFailed); } if registry_contract != self.registry_contract { - return Err(AssetResolutionFailed) + return Err(AssetResolutionFailed); } if erc20_network.is_some() && erc20_network != &Some(*self.bridged_location) { - return Err(AssetResolutionFailed) + return Err(AssetResolutionFailed); } (H160(*erc20_contract), *amount) } else { - return Err(AssetResolutionFailed) + return Err(AssetResolutionFailed); } }; - Ok(Message::NativeTokens(NativeTokensMessage::Unlock { asset, destination, amount })) + Ok(AgentExecuteCommand::TransferToken { token: asset, recipient: destination, amount }) } fn next(&mut self) -> Result<&'a Instruction, XcmConverterError> { @@ -296,7 +316,7 @@ impl<'a, Call> XcmConverter<'a, Call> { mod tests { use frame_support::parameter_types; use hex_literal::hex; - use snowbridge_core::SubmitError; + use snowbridge_core::outbound::{MessageHash, SubmitError}; use super::*; @@ -304,39 +324,34 @@ mod tests { const RelayNetwork: NetworkId = Polkadot; const UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(RelayNetwork::get()), Parachain(1013)); const BridgedNetwork: NetworkId = Ethereum{ chain_id: 1 }; - BridgedLocation: MultiLocation = MultiLocation::new(0, (GlobalConsensus(BridgedNetwork::get()), AccountKey20 { network: None, key: BRIDGE_REGISTRY })); + BridgedLocation: MultiLocation = MultiLocation::new(0, (GlobalConsensus(BridgedNetwork::get()), AccountKey20 { network: None, key: GATEWAY })); BridgedLocationWithoutRegistry: MultiLocation = MultiLocation::new(0, GlobalConsensus(BridgedNetwork::get())); - BridgedLocationWithoutGlobalConsensus: MultiLocation = MultiLocation::new(0, AccountKey20 { network: None, key: BRIDGE_REGISTRY }); + BridgedLocationWithoutGlobalConsensus: MultiLocation = MultiLocation::new(0, AccountKey20 { network: None, key: GATEWAY }); } - type Ticket = (Vec, XcmHash); - - const BRIDGE_REGISTRY: [u8; 20] = hex!("D184c103F7acc340847eEE82a0B909E3358bc28d"); - const SUCCESS_CASE_1_TICKET: [u8; 232] = hex!("e80300000100810300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e8"); - const SUCCESS_CASE_1_TICKET_HASH: [u8; 32] = - hex!("1454532f17679d9bfd775fef52de6c0598e34def65ef19ac06c11af013d6ca0f"); + const GATEWAY: [u8; 20] = hex!("D184c103F7acc340847eEE82a0B909E3358bc28d"); struct MockOkOutboundQueue; impl OutboundQueueTrait for MockOkOutboundQueue { type Ticket = (); - fn validate(_: &OutboundMessage) -> Result<(), SubmitError> { + fn validate(_: &Message) -> Result<(), SubmitError> { Ok(()) } - fn submit(_: Self::Ticket) -> Result<(), SubmitError> { - Ok(()) + fn submit(_: Self::Ticket) -> Result { + Ok(MessageHash::zero()) } } struct MockErrOutboundQueue; impl OutboundQueueTrait for MockErrOutboundQueue { type Ticket = (); - fn validate(_: &OutboundMessage) -> Result<(), SubmitError> { + fn validate(_: &Message) -> Result<(), SubmitError> { Err(SubmitError::MessageTooLarge) } - fn submit(_: Self::Ticket) -> Result<(), SubmitError> { + fn submit(_: Self::Ticket) -> Result { Err(SubmitError::MessageTooLarge) } } @@ -350,13 +365,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::NotApplicable)); } @@ -369,13 +383,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::MissingArgument)); } @@ -390,13 +403,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::NotApplicable)); } @@ -409,13 +421,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::MissingArgument)); } @@ -428,13 +439,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::Unroutable)); } @@ -451,6 +461,7 @@ mod tests { UniversalLocation, BridgedLocationWithoutGlobalConsensus, MockOkOutboundQueue, + AgentHashedDescription, >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::NotApplicable)); } @@ -468,6 +479,7 @@ mod tests { UniversalLocation, BridgedLocationWithoutRegistry, MockOkOutboundQueue, + AgentHashedDescription, >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::NotApplicable)); } @@ -482,13 +494,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::NotApplicable)); } @@ -502,13 +513,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::MissingArgument)); } @@ -522,13 +532,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::MissingArgument)); } @@ -542,13 +551,12 @@ mod tests { let mut message: Option> = None; let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::MissingArgument)); } @@ -569,7 +577,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -598,13 +606,12 @@ mod tests { ); let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::Unroutable)); } @@ -626,13 +633,12 @@ mod tests { ); let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert_eq!(result, Err(SendError::Unroutable)); } @@ -652,7 +658,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -680,35 +686,24 @@ mod tests { ); let result = - EthereumBlobExporter::::validate( - network, - channel, - &mut universal_source, - &mut destination, - &mut message, - ); + EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockOkOutboundQueue, + AgentHashedDescription, + >::validate(network, channel, &mut universal_source, &mut destination, &mut message); assert!(result.is_ok()); } - #[test] - fn exporter_deliver_success_case_1() { - let ticket: Ticket = (SUCCESS_CASE_1_TICKET.to_vec(), SUCCESS_CASE_1_TICKET_HASH); - let result = - EthereumBlobExporter::::deliver( - ticket, - ); - - assert_eq!(result, Ok(SUCCESS_CASE_1_TICKET_HASH)) - } - #[test] fn exporter_deliver_with_submit_failure_yields_unroutable() { - let ticket: Ticket = (SUCCESS_CASE_1_TICKET.to_vec(), SUCCESS_CASE_1_TICKET_HASH); - let result = - EthereumBlobExporter::::deliver( - ticket, - ); + let result = EthereumBlobExporter::< + UniversalLocation, + BridgedLocation, + MockErrOutboundQueue, + AgentHashedDescription, + >::deliver(hex!("deadbeef").to_vec()); assert_eq!(result, Err(SendError::Transport("other transport error"))) } @@ -725,7 +720,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -746,12 +741,12 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); - let expected_payload = Message::NativeTokens(NativeTokensMessage::Unlock { - asset: H160(token_address), - destination: H160(beneficiary_address), + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); + let expected_payload = AgentExecuteCommand::TransferToken { + token: H160(token_address), + recipient: H160(beneficiary_address), amount: 1000, - }); + }; let result = converter.convert(); assert_eq!(result, Ok((expected_payload, Some(&fee)))); } @@ -766,7 +761,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -786,12 +781,12 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); - let expected_payload = Message::NativeTokens(NativeTokensMessage::Unlock { - asset: H160(token_address), - destination: H160(beneficiary_address), + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); + let expected_payload = AgentExecuteCommand::TransferToken { + token: H160(token_address), + recipient: H160(beneficiary_address), amount: 1000, - }); + }; let result = converter.convert(); assert_eq!(result, Ok((expected_payload, None))); } @@ -806,7 +801,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -826,12 +821,12 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); - let expected_payload = Message::NativeTokens(NativeTokensMessage::Unlock { - asset: H160(token_address), - destination: H160(beneficiary_address), + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); + let expected_payload = AgentExecuteCommand::TransferToken { + token: H160(token_address), + recipient: H160(beneficiary_address), amount: 1000, - }); + }; let result = converter.convert(); assert_eq!(result, Ok((expected_payload, None))); } @@ -844,7 +839,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -858,9 +853,9 @@ mod tests { ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::UnexpectedEndOfXcm)); + assert_eq!(result.err(), Some(XcmConverterError::UnexpectedEndOfXcm)); } #[test] @@ -869,10 +864,10 @@ mod tests { let message: Xcm<()> = vec![].into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::UnexpectedEndOfXcm)); + assert_eq!(result.err(), Some(XcmConverterError::UnexpectedEndOfXcm)); } #[test] @@ -885,7 +880,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -905,10 +900,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::TargetFeeExpected)); + assert_eq!(result.err(), Some(XcmConverterError::TargetFeeExpected)); } #[test] @@ -924,7 +919,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -945,10 +940,10 @@ mod tests { ClearTopic, ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::SetTopicExpected)); + assert_eq!(result.err(), Some(XcmConverterError::SetTopicExpected)); } #[test] @@ -964,7 +959,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -986,10 +981,10 @@ mod tests { ClearOrigin, ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::EndOfXcmMessageExpected)); + assert_eq!(result.err(), Some(XcmConverterError::EndOfXcmMessageExpected)); } #[test] @@ -1005,7 +1000,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1025,10 +1020,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::WithdrawExpected)); + assert_eq!(result.err(), Some(XcmConverterError::WithdrawExpected)); } #[test] @@ -1043,7 +1038,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1059,10 +1054,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::DepositExpected)); + assert_eq!(result.err(), Some(XcmConverterError::DepositExpected)); } #[test] @@ -1088,10 +1083,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::NoReserveAssets)); + assert_eq!(result.err(), Some(XcmConverterError::NoReserveAssets)); } #[test] @@ -1129,10 +1124,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::TooManyAssets)); + assert_eq!(result.err(), Some(XcmConverterError::TooManyAssets)); } #[test] @@ -1148,7 +1143,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1169,10 +1164,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::FilterDoesNotConsumeAllAssets)); + assert_eq!(result.err(), Some(XcmConverterError::FilterDoesNotConsumeAllAssets)); } #[test] @@ -1188,7 +1183,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1209,10 +1204,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::AssetNotConcreteFungible)); + assert_eq!(result.err(), Some(XcmConverterError::AssetNotConcreteFungible)); } #[test] @@ -1228,7 +1223,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1249,10 +1244,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::ZeroAssetTransfer)); + assert_eq!(result.err(), Some(XcmConverterError::ZeroAssetTransfer)); } #[test] @@ -1282,10 +1277,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::AssetResolutionFailed)); + assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); } #[test] @@ -1301,7 +1296,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: Some(network), key: BRIDGE_REGISTRY }, + AccountKey20 { network: Some(network), key: GATEWAY }, AccountKey20 { network: Some(Ethereum { chain_id: 2 }), key: token_address }, ) .into(), @@ -1322,10 +1317,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::AssetResolutionFailed)); + assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); } #[test] @@ -1364,10 +1359,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::AssetResolutionFailed)); + assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); } #[test] @@ -1383,7 +1378,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: Some(Ethereum { chain_id: 2 }), key: BRIDGE_REGISTRY }, + AccountKey20 { network: Some(Ethereum { chain_id: 2 }), key: GATEWAY }, AccountKey20 { network: Some(network), key: token_address }, ) .into(), @@ -1404,10 +1399,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::AssetResolutionFailed)); + assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); } #[test] @@ -1425,7 +1420,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1451,10 +1446,10 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::BeneficiaryResolutionFailed)); + assert_eq!(result.err(), Some(XcmConverterError::BeneficiaryResolutionFailed)); } #[test] @@ -1471,7 +1466,7 @@ mod tests { let assets: MultiAssets = vec![MultiAsset { id: Concrete( X2( - AccountKey20 { network: None, key: BRIDGE_REGISTRY }, + AccountKey20 { network: None, key: GATEWAY }, AccountKey20 { network: None, key: token_address }, ) .into(), @@ -1496,9 +1491,9 @@ mod tests { SetTopic([0; 32]), ] .into(); - let mut converter = XcmConverter::new(&message, &network, &BRIDGE_REGISTRY); + let mut converter = XcmConverter::new(&message, &network, &GATEWAY); let result = converter.convert(); - assert_eq!(result, Err(XcmConverterError::BeneficiaryResolutionFailed)); + assert_eq!(result.err(), Some(XcmConverterError::BeneficiaryResolutionFailed)); } } diff --git a/parachain/primitives/router/src/outbound/payload.rs b/parachain/primitives/router/src/outbound/payload.rs deleted file mode 100644 index f7f9454950067..0000000000000 --- a/parachain/primitives/router/src/outbound/payload.rs +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use ethabi::{self, Token}; - -use hex_literal::hex; -use snowbridge_core::ContractId; -use sp_core::{RuntimeDebug, H160}; -use sp_std::prelude::*; - -#[derive(Clone, PartialEq, RuntimeDebug)] -pub enum Message { - UpgradeProxy(UpgradeProxyMessage), - NativeTokens(NativeTokensMessage), -} - -/// A message to be sent to `UpgradeProxy.sol`. -#[derive(Clone, PartialEq, RuntimeDebug)] -pub enum UpgradeProxyMessage { - /// Run an upgrade task with elevated privileges - Upgrade { - /// The address of the upgrader contract which implements `UpgradeTask.sol`. - upgrade_task: H160, - }, -} - -/// A message to be sent to `NativeTokens.sol`. -#[derive(Clone, PartialEq, RuntimeDebug)] -pub enum NativeTokensMessage { - /// Release locked collateral for ERC20 token identified by `asset` back to the specified - /// `destination` account - Unlock { - /// ERC20 token address - asset: H160, - /// Account which will receive the tokens - destination: H160, - /// Amount of tokens to release - amount: u128, - }, -} - -impl Message { - /// Encodes the payload so that it can executed on the Ethereum side of the bridge. - /// - /// Returns: - /// * A stable identifier for a receiving gateway contract within Registry.sol. - /// * The payload passed to the Gateway contract's `handle(origin, message)` method. - pub fn encode(&self) -> (ContractId, Vec) { - match self { - Self::UpgradeProxy(UpgradeProxyMessage::Upgrade { upgrade_task }) => { - let inner = ethabi::encode(&[Token::Tuple(vec![Token::Address(*upgrade_task)])]); - let message = ethabi::encode(&[Token::Tuple(vec![ - Token::Uint(0.into()), // Upgrade action = 0 - Token::Bytes(inner), - ])]); - ( - // keccak256("UpgradeProxy") - hex!["44bef07c29162ad04096f5cbe78ca2df62dffe97cea85825f08d13319e13f34a"].into(), - message, - ) - }, - Self::NativeTokens(NativeTokensMessage::Unlock { asset, destination, amount }) => { - let inner = ethabi::encode(&[Token::Tuple(vec![ - Token::Address(*asset), - Token::Address(*destination), - Token::Uint((*amount).into()), - ])]); - let message = ethabi::encode(&[Token::Tuple(vec![ - Token::Uint(0.into()), // Unlock action = 0 - Token::Bytes(inner), - ])]); - ( - // keccak256("NativeTokens") - hex!["1d0761c5c76335b59fce9e8070a90d04470a4d5806c9814b73032db3dbb843ea"].into(), - message, - ) - }, - } - } -} diff --git a/parachain/primitives/testutils/Cargo.toml b/parachain/primitives/testutils/Cargo.toml deleted file mode 100644 index ae708e74af304..0000000000000 --- a/parachain/primitives/testutils/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "snowbridge-testutils" -version = "0.1.0" -authors = [ "Snowfork " ] -edition = "2021" - -[dependencies] -ethereum-types = { version = "0.14.1", default-features = false } -hex = { package = "rustc-hex", version = "2.1.0", default-features = false } -serde = { version = "1.0.164", features = [ "derive" ] } -serde_json = "1.0.96" diff --git a/parachain/primitives/testutils/src/lib.rs b/parachain/primitives/testutils/src/lib.rs deleted file mode 100644 index e2ae97f12ca96..0000000000000 --- a/parachain/primitives/testutils/src/lib.rs +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use ethereum_types::{H128, H256, H512}; -use serde::{Deserialize, Deserializer}; -use std::{fs::File, path::Path}; - -/// The structs defined below are used to load Ethash merkle proofs -/// generated by https://github.com/talbaneth/ethashproof. -/// To generate proof JSON: -/// ./cmd/relayer/relayer $BLOCK_NUM -/// To load in test: -/// $proof_data = BlockWithProofs::from_file("path/to/proof.json") -/// .to_double_node_with_merkle_proof_vec(); - -#[derive(Clone)] -pub struct Hex(pub Vec); - -impl<'de> Deserialize<'de> for Hex { - fn deserialize(deserializer: D) -> Result>::Error> - where - D: Deserializer<'de>, - { - let mut s = ::deserialize(deserializer)?; - if s.starts_with("0x") { - s = s[2..].to_string(); - } - if s.len() % 2 == 1 { - s.insert_str(0, "0"); - } - let v: Vec = hex::FromHexIter::new(&s).map(|x| x.unwrap()).collect(); - Ok(Hex(v)) - } -} - -impl From<&Hex> for H256 { - fn from(item: &Hex) -> Self { - let mut data = [0u8; 32]; - let size = item.0.len(); - for i in 0..size { - data[31 - i] = item.0[size - 1 - i]; - } - data.into() - } -} - -impl From<&Hex> for H128 { - fn from(item: &Hex) -> Self { - let mut data = [0u8; 16]; - let size = item.0.len(); - for i in 0..size { - data[15 - i] = item.0[size - 1 - i]; - } - data.into() - } -} - -#[derive(Deserialize)] -struct BlockWithProofsRaw { - pub proof_length: u64, - pub header_rlp: Hex, - pub merkle_root: Hex, // H128 - pub elements: Vec, // H256 - pub merkle_proofs: Vec, // H128 -} - -pub struct BlockWithProofs { - pub proof_length: u64, - pub header_rlp: Hex, - pub merkle_root: H128, - pub elements: Vec, - pub merkle_proofs: Vec, -} - -impl From for BlockWithProofs { - fn from(item: BlockWithProofsRaw) -> Self { - Self { - proof_length: item.proof_length, - header_rlp: item.header_rlp, - merkle_root: (&item.merkle_root).into(), - elements: item.elements.iter().map(|e| e.into()).collect(), - merkle_proofs: item.merkle_proofs.iter().map(|e| e.into()).collect(), - } - } -} - -impl BlockWithProofs { - pub fn from_file(path: &Path) -> Self { - let raw: BlockWithProofsRaw = serde_json::from_reader(File::open(path).unwrap()).unwrap(); - raw.into() - } - - fn combine_dag_h256_to_h512(elements: Vec) -> Vec { - elements - .iter() - .zip(elements.iter().skip(1)) - .enumerate() - .filter(|(i, _)| i % 2 == 0) - .map(|(_, (a, b))| { - let mut buffer = [0u8; 64]; - buffer[..32].copy_from_slice(&(a.0)); - buffer[32..].copy_from_slice(&(b.0)); - buffer.into() - }) - .collect() - } - - pub fn to_double_node_with_merkle_proof_vec( - &self, - mapper: fn([H512; 2], Vec) -> T, - ) -> Vec { - let h512s = Self::combine_dag_h256_to_h512(self.elements.clone()); - h512s - .iter() - .zip(h512s.iter().skip(1)) - .enumerate() - .filter(|(i, _)| i % 2 == 0) - .map(|(i, (a, b))| { - mapper( - [*a, *b], - self.merkle_proofs[i / 2 * self.proof_length as usize.. - (i / 2 + 1) * self.proof_length as usize] - .to_vec(), - ) - }) - .collect() - } -} diff --git a/relayer/README.md b/relayer/README.md index 2825f6fd0c727..93de5ed22e7c0 100644 --- a/relayer/README.md +++ b/relayer/README.md @@ -28,7 +28,7 @@ To enable revive for linting in VS-code, add the following to your config: The relayer relies on dynamically generated bindings for our Ethereum contracts. They need to be updated whenever the contracts change. -Compile the contracts in the [contracts](../core/packages/contracts) directory: +Compile the contracts in the [contracts](../contracts) directory: ```bash pnpm build @@ -51,9 +51,9 @@ sszgen --path relays/beacon/state/beacon.go --objs BeaconStateCapellaMinimal,Bea ## Configuration -Note: For local development and testing, we use our E2E test stack described [here](../core/packages/test/README.md). It automatically generates suitable relayer configurations for testing. +Note: For local development and testing, we use our E2E test stack described [here](../web/packages/test/README.md). It automatically generates suitable relayer configurations for testing. -For an example configuration, please consult the [setup script](https://github.com/Snowfork/snowbridge/blob/main/core/packages/test/scripts/start-services.sh) for our local development stack. Specifically the `start_relayer` bash function. +For an example configuration, please consult the [setup script](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/scripts/start-services.sh) for our local development stack. Specifically the `start_relayer` bash function. ## Tests diff --git a/relayer/chain/ethereum/connection.go b/relayer/chain/ethereum/connection.go index 07bce9258e9a2..a56d898682443 100644 --- a/relayer/chain/ethereum/connection.go +++ b/relayer/chain/ethereum/connection.go @@ -6,14 +6,20 @@ package ethereum import ( "context" "encoding/hex" + "errors" + "fmt" "math/big" + "time" "github.com/ethereum/go-ethereum" + goEthereum "github.com/ethereum/go-ethereum" + "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/ethclient" "github.com/sirupsen/logrus" + "github.com/snowfork/snowbridge/relayer/config" "github.com/snowfork/snowbridge/relayer/crypto/secp256k1" log "github.com/sirupsen/logrus" @@ -24,12 +30,20 @@ type Connection struct { kp *secp256k1.Keypair client *ethclient.Client chainID *big.Int + config *config.EthereumConfig } -func NewConnection(endpoint string, kp *secp256k1.Keypair) *Connection { +type JsonError interface { + Error() string + ErrorCode() int + ErrorData() interface{} +} + +func NewConnection(config *config.EthereumConfig, kp *secp256k1.Keypair) *Connection { return &Connection{ - endpoint: endpoint, + endpoint: config.Endpoint, kp: kp, + config: config, } } @@ -73,15 +87,15 @@ func (co *Connection) ChainID() *big.Int { return co.chainID } -func (co *Connection) QueryFailingMessage(hash common.Hash) (string, error) { - tx, _, err := co.client.TransactionByHash(context.Background(), hash) +func (co *Connection) queryFailingError(ctx context.Context, hash common.Hash) error { + tx, _, err := co.client.TransactionByHash(ctx, hash) if err != nil { - return "", err + return err } - from, err := types.Sender(types.NewEIP155Signer(tx.ChainId()), tx) + from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx) if err != nil { - return "", err + return err } params := ethereum.CallMsg{ @@ -105,10 +119,103 @@ func (co *Connection) QueryFailingMessage(hash common.Hash) (string, error) { // The logger does a test call to the actual contract to check for any revert message and log it, as well // as logging the call info. This is because the golang client can sometimes suppress the log message and so // it can be helpful to use the call info to do the same call in Truffle/Web3js to get better logs. - res, err := co.client.CallContract(context.Background(), params, nil) + _, err = co.client.CallContract(ctx, params, nil) + if err != nil { + return err + } + return nil +} + +func (co *Connection) waitForTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { + for { + receipt, err := co.pollTransaction(ctx, tx, confirmations) + if err != nil { + return nil, err + } + + if receipt != nil { + return receipt, nil + } + + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(500 * time.Millisecond): + } + } +} + +func (co *Connection) pollTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { + receipt, err := co.Client().TransactionReceipt(ctx, tx.Hash()) + if err != nil { + if errors.Is(err, goEthereum.NotFound) { + return nil, nil + } + } + + latestHeader, err := co.Client().HeaderByNumber(ctx, nil) + if err != nil { + return nil, err + } + + if latestHeader.Number.Uint64()-receipt.BlockNumber.Uint64() >= confirmations { + return receipt, nil + } + + return nil, nil +} + +func (co *Connection) WatchTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { + receipt, err := co.waitForTransaction(ctx, tx, confirmations) if err != nil { - return "", err + return nil, err + } + if receipt.Status != 1 { + err = co.queryFailingError(ctx, receipt.TxHash) + logFields := log.Fields{ + "txHash": tx.Hash().Hex(), + } + if err != nil { + logFields["error"] = err.Error() + jsonErr, ok := err.(JsonError) + if ok { + errorCode := fmt.Sprintf("%v", jsonErr.ErrorData()) + logFields["code"] = errorCode + } + } + log.WithFields(logFields).Error("Failed to send transaction") + return receipt, err + } + return receipt, nil +} + +func (co *Connection) MakeTxOpts(ctx context.Context) *bind.TransactOpts { + chainID := co.ChainID() + keypair := co.Keypair() + + options := bind.TransactOpts{ + From: keypair.CommonAddress(), + Signer: func(_ common.Address, tx *types.Transaction) (*types.Transaction, error) { + return types.SignTx(tx, types.LatestSignerForChainID(chainID), keypair.PrivateKey()) + }, + Context: ctx, + } + + if co.config.GasFeeCap > 0 { + fee := big.NewInt(0) + fee.SetUint64(co.config.GasFeeCap) + options.GasFeeCap = fee + } + + if co.config.GasTipCap > 0 { + tip := big.NewInt(0) + tip.SetUint64(co.config.GasTipCap) + options.GasTipCap = tip + } + + if co.config.GasLimit > 0 { + options.GasLimit = co.config.GasLimit } - return string(res), nil + return &options } diff --git a/relayer/chain/ethereum/connection_test.go b/relayer/chain/ethereum/connection_test.go deleted file mode 100644 index 41d4a3c258f39..0000000000000 --- a/relayer/chain/ethereum/connection_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Snowfork -// SPDX-License-Identifier: LGPL-3.0-only - -package ethereum_test - -import ( - "context" - "testing" - - "github.com/snowfork/snowbridge/relayer/chain/ethereum" - "github.com/snowfork/snowbridge/relayer/crypto/secp256k1" -) - -func TestConnect(t *testing.T) { - conn := ethereum.NewConnection("ws://127.0.0.1:8546", secp256k1.Alice()) - err := conn.Connect(context.Background()) - if err != nil { - t.Fatal(err) - } - defer conn.Close() -} diff --git a/relayer/chain/ethereum/message.go b/relayer/chain/ethereum/message.go index 1bd36c5e8aad0..9659ec18675e0 100644 --- a/relayer/chain/ethereum/message.go +++ b/relayer/chain/ethereum/message.go @@ -50,6 +50,7 @@ func MakeMessageFromEvent(event *etypes.Log, receiptsTrie *etrie.Trie) (*paracha "payload": value, "blockHash": m.Proof.BlockHash.Hex(), "eventIndex": m.Proof.TxIndex, + "txHash": event.TxHash.Hex(), }).Debug("Generated message from Ethereum log") return &m, nil diff --git a/relayer/chain/parachain/writer.go b/relayer/chain/parachain/writer.go index 3c82e74c1890f..8e35ff98aca1a 100644 --- a/relayer/chain/parachain/writer.go +++ b/relayer/chain/parachain/writer.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" + log "github.com/sirupsen/logrus" "github.com/snowfork/go-substrate-rpc-client/v4/rpc/author" "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/relays/beacon/header/syncer/scale" @@ -120,6 +121,8 @@ func (wr *ParachainWriter) WriteToParachainAndWatch(ctx context.Context, extrins return fmt.Errorf("parachain write status was dropped, invalid, usurped or finality timed out") } if status.IsFinalized { + log.WithFields(log.Fields{ + "extrinsic": extrinsicName, "block": status.AsFinalized}).Debug("extrinsic finalized") return nil } case err = <-sub.Err(): diff --git a/relayer/cmd/generate_beacon_data.go b/relayer/cmd/generate_beacon_data.go index eb3cb60fb47dc..483fe733cde3a 100644 --- a/relayer/cmd/generate_beacon_data.go +++ b/relayer/cmd/generate_beacon_data.go @@ -95,7 +95,7 @@ func generateBeaconCheckpoint(cmd *cobra.Command, _ []string) error { endpoint, err := cmd.Flags().GetString("url") - viper.SetConfigFile("core/packages/test/config/beacon-relay.json") + viper.SetConfigFile("web/packages/test/config/beacon-relay.json") if err := viper.ReadInConfig(); err != nil { return err @@ -151,7 +151,7 @@ func generateBeaconData(cmd *cobra.Command, _ []string) error { endpoint, _ := cmd.Flags().GetString("url") - viper.SetConfigFile("core/packages/test/config/beacon-relay.json") + viper.SetConfigFile("web/packages/test/config/beacon-relay.json") if err := viper.ReadInConfig(); err != nil { return err } diff --git a/relayer/cmd/import_execution_header.go b/relayer/cmd/import_execution_header.go index b88e313ccbb1e..855d4c67c0240 100644 --- a/relayer/cmd/import_execution_header.go +++ b/relayer/cmd/import_execution_header.go @@ -79,7 +79,7 @@ func importExecutionHeaderFn(cmd *cobra.Command, _ []string) error { spec, _ := cmd.Flags().GetString("spec") activeSpec, _ := config.ToSpec(spec) - viper.SetConfigFile("core/packages/test/config/beacon-relay.json") + viper.SetConfigFile("web/packages/test/config/beacon-relay.json") if err := viper.ReadInConfig(); err != nil { return err } diff --git a/relayer/contracts/beefy_client.go b/relayer/contracts/beefy_client.go index 96c5122019ff0..17a791c812645 100644 --- a/relayer/contracts/beefy_client.go +++ b/relayer/contracts/beefy_client.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // BeefyClientCommitment is an auto generated low-level Go binding around an user-defined struct. @@ -71,7 +72,7 @@ type BeefyClientValidatorSet struct { // BeefyClientMetaData contains all meta data concerning the BeefyClient contract. var BeefyClientMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_randaoCommitDelay\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_randaoCommitExpiration\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBitfield\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMMRLeaf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMMRLeafProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMMRRootLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTask\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidValidatorProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoMMRRootInCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughClaims\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrevRandaoAlreadyCaptured\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrevRandaoNotCaptured\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TicketExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WaitPeriodNotOver\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"mmrRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"blockNumber\",\"type\":\"uint64\"}],\"name\":\"NewMMRRoot\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitmentHash\",\"type\":\"bytes32\"}],\"name\":\"commitPrevRandao\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitmentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"}],\"name\":\"createFinalBitfield\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"bitsToSet\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"createInitialBitfield\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_initialBeefyBlock\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structBeefyClient.ValidatorSet\",\"name\":\"_initialValidatorSet\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structBeefyClient.ValidatorSet\",\"name\":\"_nextValidatorSet\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBeefyBlock\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestMMRRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mmrRootID\",\"outputs\":[{\"internalType\":\"bytes2\",\"name\":\"\",\"type\":\"bytes2\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextValidatorSet\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"randaoCommitDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"randaoCommitExpiration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"name\":\"proofs\",\"type\":\"tuple[]\"}],\"name\":\"submitFinal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"name\":\"proofs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"parentNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"parentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structBeefyClient.MMRLeaf\",\"name\":\"leaf\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"leafProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"leafProofOrder\",\"type\":\"uint256\"}],\"name\":\"submitFinalWithHandover\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"submitInitial\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"submitInitialWithHandover\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"tickets\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"blockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"validatorSetLen\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"prevRandao\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"bitfieldHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofOrder\",\"type\":\"uint256\"}],\"name\":\"verifyMMRLeafProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_randaoCommitDelay\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_randaoCommitExpiration\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_initialBeefyBlock\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structBeefyClient.ValidatorSet\",\"name\":\"_initialValidatorSet\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structBeefyClient.ValidatorSet\",\"name\":\"_nextValidatorSet\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBitfield\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBitfieldLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMMRLeaf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMMRLeafProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMMRRootLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTicket\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidValidatorProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoMMRRootInCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughClaims\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrevRandaoAlreadyCaptured\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PrevRandaoNotCaptured\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ProofSizeExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TicketExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedCompactEncoding\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WaitPeriodNotOver\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"mmrRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"blockNumber\",\"type\":\"uint64\"}],\"name\":\"NewMMRRoot\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MMR_ROOT_ID\",\"outputs\":[{\"internalType\":\"bytes2\",\"name\":\"\",\"type\":\"bytes2\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitmentHash\",\"type\":\"bytes32\"}],\"name\":\"commitPrevRandao\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitmentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"}],\"name\":\"createFinalBitfield\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"bitsToSet\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"createInitialBitfield\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentValidatorSet\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestBeefyBlock\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestMMRRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextValidatorSet\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"id\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"length\",\"type\":\"uint128\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"randaoCommitDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"randaoCommitExpiration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"name\":\"proofs\",\"type\":\"tuple[]\"}],\"name\":\"submitFinal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"name\":\"proofs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"parentNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"parentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structBeefyClient.MMRLeaf\",\"name\":\"leaf\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"leafProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"leafProofOrder\",\"type\":\"uint256\"}],\"name\":\"submitFinalWithHandover\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"submitInitial\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"validatorSetID\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes2\",\"name\":\"payloadID\",\"type\":\"bytes2\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structBeefyClient.PayloadItem[]\",\"name\":\"payload\",\"type\":\"tuple[]\"}],\"internalType\":\"structBeefyClient.Commitment\",\"name\":\"commitment\",\"type\":\"tuple\"},{\"internalType\":\"uint256[]\",\"name\":\"bitfield\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structBeefyClient.ValidatorProof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"submitInitialWithHandover\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"tickets\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"blockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"validatorSetLen\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"prevRandao\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"bitfieldHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofOrder\",\"type\":\"uint256\"}],\"name\":\"verifyMMRLeafProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", } // BeefyClientABI is the input ABI used to generate the binding from. @@ -175,11 +176,11 @@ func NewBeefyClientFilterer(address common.Address, filterer bind.ContractFilter // bindBeefyClient binds a generic wrapper to an already deployed contract. func bindBeefyClient(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(BeefyClientABI)) + parsed, err := BeefyClientMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and @@ -220,6 +221,37 @@ func (_BeefyClient *BeefyClientTransactorRaw) Transact(opts *bind.TransactOpts, return _BeefyClient.Contract.contract.Transact(opts, method, params...) } +// MMRROOTID is a free data retrieval call binding the contract method 0x0a7c8faa. +// +// Solidity: function MMR_ROOT_ID() view returns(bytes2) +func (_BeefyClient *BeefyClientCaller) MMRROOTID(opts *bind.CallOpts) ([2]byte, error) { + var out []interface{} + err := _BeefyClient.contract.Call(opts, &out, "MMR_ROOT_ID") + + if err != nil { + return *new([2]byte), err + } + + out0 := *abi.ConvertType(out[0], new([2]byte)).(*[2]byte) + + return out0, err + +} + +// MMRROOTID is a free data retrieval call binding the contract method 0x0a7c8faa. +// +// Solidity: function MMR_ROOT_ID() view returns(bytes2) +func (_BeefyClient *BeefyClientSession) MMRROOTID() ([2]byte, error) { + return _BeefyClient.Contract.MMRROOTID(&_BeefyClient.CallOpts) +} + +// MMRROOTID is a free data retrieval call binding the contract method 0x0a7c8faa. +// +// Solidity: function MMR_ROOT_ID() view returns(bytes2) +func (_BeefyClient *BeefyClientCallerSession) MMRROOTID() ([2]byte, error) { + return _BeefyClient.Contract.MMRROOTID(&_BeefyClient.CallOpts) +} + // CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. // // Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) @@ -394,37 +426,6 @@ func (_BeefyClient *BeefyClientCallerSession) LatestMMRRoot() ([32]byte, error) return _BeefyClient.Contract.LatestMMRRoot(&_BeefyClient.CallOpts) } -// MmrRootID is a free data retrieval call binding the contract method 0xa9b19412. -// -// Solidity: function mmrRootID() view returns(bytes2) -func (_BeefyClient *BeefyClientCaller) MmrRootID(opts *bind.CallOpts) ([2]byte, error) { - var out []interface{} - err := _BeefyClient.contract.Call(opts, &out, "mmrRootID") - - if err != nil { - return *new([2]byte), err - } - - out0 := *abi.ConvertType(out[0], new([2]byte)).(*[2]byte) - - return out0, err - -} - -// MmrRootID is a free data retrieval call binding the contract method 0xa9b19412. -// -// Solidity: function mmrRootID() view returns(bytes2) -func (_BeefyClient *BeefyClientSession) MmrRootID() ([2]byte, error) { - return _BeefyClient.Contract.MmrRootID(&_BeefyClient.CallOpts) -} - -// MmrRootID is a free data retrieval call binding the contract method 0xa9b19412. -// -// Solidity: function mmrRootID() view returns(bytes2) -func (_BeefyClient *BeefyClientCallerSession) MmrRootID() ([2]byte, error) { - return _BeefyClient.Contract.MmrRootID(&_BeefyClient.CallOpts) -} - // NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. // // Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) @@ -475,37 +476,6 @@ func (_BeefyClient *BeefyClientCallerSession) NextValidatorSet() (struct { return _BeefyClient.Contract.NextValidatorSet(&_BeefyClient.CallOpts) } -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_BeefyClient *BeefyClientCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BeefyClient.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 - -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_BeefyClient *BeefyClientSession) Owner() (common.Address, error) { - return _BeefyClient.Contract.Owner(&_BeefyClient.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_BeefyClient *BeefyClientCallerSession) Owner() (common.Address, error) { - return _BeefyClient.Contract.Owner(&_BeefyClient.CallOpts) -} - // RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. // // Solidity: function randaoCommitDelay() view returns(uint256) @@ -680,48 +650,6 @@ func (_BeefyClient *BeefyClientTransactorSession) CommitPrevRandao(commitmentHas return _BeefyClient.Contract.CommitPrevRandao(&_BeefyClient.TransactOpts, commitmentHash) } -// Initialize is a paid mutator transaction binding the contract method 0xe104815d. -// -// Solidity: function initialize(uint64 _initialBeefyBlock, (uint128,uint128,bytes32) _initialValidatorSet, (uint128,uint128,bytes32) _nextValidatorSet) returns() -func (_BeefyClient *BeefyClientTransactor) Initialize(opts *bind.TransactOpts, _initialBeefyBlock uint64, _initialValidatorSet BeefyClientValidatorSet, _nextValidatorSet BeefyClientValidatorSet) (*types.Transaction, error) { - return _BeefyClient.contract.Transact(opts, "initialize", _initialBeefyBlock, _initialValidatorSet, _nextValidatorSet) -} - -// Initialize is a paid mutator transaction binding the contract method 0xe104815d. -// -// Solidity: function initialize(uint64 _initialBeefyBlock, (uint128,uint128,bytes32) _initialValidatorSet, (uint128,uint128,bytes32) _nextValidatorSet) returns() -func (_BeefyClient *BeefyClientSession) Initialize(_initialBeefyBlock uint64, _initialValidatorSet BeefyClientValidatorSet, _nextValidatorSet BeefyClientValidatorSet) (*types.Transaction, error) { - return _BeefyClient.Contract.Initialize(&_BeefyClient.TransactOpts, _initialBeefyBlock, _initialValidatorSet, _nextValidatorSet) -} - -// Initialize is a paid mutator transaction binding the contract method 0xe104815d. -// -// Solidity: function initialize(uint64 _initialBeefyBlock, (uint128,uint128,bytes32) _initialValidatorSet, (uint128,uint128,bytes32) _nextValidatorSet) returns() -func (_BeefyClient *BeefyClientTransactorSession) Initialize(_initialBeefyBlock uint64, _initialValidatorSet BeefyClientValidatorSet, _nextValidatorSet BeefyClientValidatorSet) (*types.Transaction, error) { - return _BeefyClient.Contract.Initialize(&_BeefyClient.TransactOpts, _initialBeefyBlock, _initialValidatorSet, _nextValidatorSet) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_BeefyClient *BeefyClientTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BeefyClient.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_BeefyClient *BeefyClientSession) RenounceOwnership() (*types.Transaction, error) { - return _BeefyClient.Contract.RenounceOwnership(&_BeefyClient.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_BeefyClient *BeefyClientTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _BeefyClient.Contract.RenounceOwnership(&_BeefyClient.TransactOpts) -} - // SubmitFinal is a paid mutator transaction binding the contract method 0x719321f0. // // Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs) returns() @@ -766,67 +694,46 @@ func (_BeefyClient *BeefyClientTransactorSession) SubmitFinalWithHandover(commit // SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. // -// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) payable returns() +// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() func (_BeefyClient *BeefyClientTransactor) SubmitInitial(opts *bind.TransactOpts, commitment BeefyClientCommitment, bitfield []*big.Int, proof BeefyClientValidatorProof) (*types.Transaction, error) { return _BeefyClient.contract.Transact(opts, "submitInitial", commitment, bitfield, proof) } // SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. // -// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) payable returns() +// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() func (_BeefyClient *BeefyClientSession) SubmitInitial(commitment BeefyClientCommitment, bitfield []*big.Int, proof BeefyClientValidatorProof) (*types.Transaction, error) { return _BeefyClient.Contract.SubmitInitial(&_BeefyClient.TransactOpts, commitment, bitfield, proof) } // SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. // -// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) payable returns() +// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() func (_BeefyClient *BeefyClientTransactorSession) SubmitInitial(commitment BeefyClientCommitment, bitfield []*big.Int, proof BeefyClientValidatorProof) (*types.Transaction, error) { return _BeefyClient.Contract.SubmitInitial(&_BeefyClient.TransactOpts, commitment, bitfield, proof) } // SubmitInitialWithHandover is a paid mutator transaction binding the contract method 0x9f837da0. // -// Solidity: function submitInitialWithHandover((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) payable returns() +// Solidity: function submitInitialWithHandover((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() func (_BeefyClient *BeefyClientTransactor) SubmitInitialWithHandover(opts *bind.TransactOpts, commitment BeefyClientCommitment, bitfield []*big.Int, proof BeefyClientValidatorProof) (*types.Transaction, error) { return _BeefyClient.contract.Transact(opts, "submitInitialWithHandover", commitment, bitfield, proof) } // SubmitInitialWithHandover is a paid mutator transaction binding the contract method 0x9f837da0. // -// Solidity: function submitInitialWithHandover((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) payable returns() +// Solidity: function submitInitialWithHandover((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() func (_BeefyClient *BeefyClientSession) SubmitInitialWithHandover(commitment BeefyClientCommitment, bitfield []*big.Int, proof BeefyClientValidatorProof) (*types.Transaction, error) { return _BeefyClient.Contract.SubmitInitialWithHandover(&_BeefyClient.TransactOpts, commitment, bitfield, proof) } // SubmitInitialWithHandover is a paid mutator transaction binding the contract method 0x9f837da0. // -// Solidity: function submitInitialWithHandover((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) payable returns() +// Solidity: function submitInitialWithHandover((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() func (_BeefyClient *BeefyClientTransactorSession) SubmitInitialWithHandover(commitment BeefyClientCommitment, bitfield []*big.Int, proof BeefyClientValidatorProof) (*types.Transaction, error) { return _BeefyClient.Contract.SubmitInitialWithHandover(&_BeefyClient.TransactOpts, commitment, bitfield, proof) } -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_BeefyClient *BeefyClientTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _BeefyClient.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_BeefyClient *BeefyClientSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _BeefyClient.Contract.TransferOwnership(&_BeefyClient.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_BeefyClient *BeefyClientTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _BeefyClient.Contract.TransferOwnership(&_BeefyClient.TransactOpts, newOwner) -} - // BeefyClientNewMMRRootIterator is returned from FilterNewMMRRoot and is used to iterate over the raw logs and unpacked data for NewMMRRoot events raised by the BeefyClient contract. type BeefyClientNewMMRRootIterator struct { Event *BeefyClientNewMMRRoot // Event containing the contract specifics and raw log @@ -961,156 +868,3 @@ func (_BeefyClient *BeefyClientFilterer) ParseNewMMRRoot(log types.Log) (*BeefyC event.Raw = log return event, nil } - -// BeefyClientOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the BeefyClient contract. -type BeefyClientOwnershipTransferredIterator struct { - Event *BeefyClientOwnershipTransferred // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientOwnershipTransferredIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientOwnershipTransferred) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientOwnershipTransferred) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientOwnershipTransferred represents a OwnershipTransferred event raised by the BeefyClient contract. -type BeefyClientOwnershipTransferred struct { - PreviousOwner common.Address - NewOwner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_BeefyClient *BeefyClientFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*BeefyClientOwnershipTransferredIterator, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _BeefyClient.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &BeefyClientOwnershipTransferredIterator{contract: _BeefyClient.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_BeefyClient *BeefyClientFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BeefyClientOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _BeefyClient.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientOwnershipTransferred) - if err := _BeefyClient.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 -} - -// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_BeefyClient *BeefyClientFilterer) ParseOwnershipTransferred(log types.Log) (*BeefyClientOwnershipTransferred, error) { - event := new(BeefyClientOwnershipTransferred) - if err := _BeefyClient.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/contracts/gateway.go b/relayer/contracts/gateway.go new file mode 100644 index 0000000000000..f9e382bea28d1 --- /dev/null +++ b/relayer/contracts/gateway.go @@ -0,0 +1,1921 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contracts + +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" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// InboundMessage is an auto generated low-level Go binding around an user-defined struct. +type InboundMessage struct { + Origin *big.Int + Nonce uint64 + Command uint8 + Params []byte +} + +// VerificationDigestItem is an auto generated low-level Go binding around an user-defined struct. +type VerificationDigestItem struct { + Kind *big.Int + ConsensusEngineID [4]byte + Data []byte +} + +// VerificationHeadProof is an auto generated low-level Go binding around an user-defined struct. +type VerificationHeadProof struct { + Pos *big.Int + Width *big.Int + Proof [][32]byte +} + +// VerificationMMRLeafPartial is an auto generated low-level Go binding around an user-defined struct. +type VerificationMMRLeafPartial struct { + Version uint8 + ParentNumber uint32 + ParentHash [32]byte + NextAuthoritySetID uint64 + NextAuthoritySetLen uint32 + NextAuthoritySetRoot [32]byte +} + +// VerificationParachainHeader is an auto generated low-level Go binding around an user-defined struct. +type VerificationParachainHeader struct { + ParentHash [32]byte + Number *big.Int + StateRoot [32]byte + ExtrinsicsRoot [32]byte + DigestItems []VerificationDigestItem +} + +// VerificationProof is an auto generated low-level Go binding around an user-defined struct. +type VerificationProof struct { + Header VerificationParachainHeader + HeadProof VerificationHeadProof + LeafPartial VerificationMMRLeafPartial + LeafProof [][32]byte + LeafProofOrder *big.Int +} + +// GatewayMetaData contains all meta data concerning the Gateway contract. +var GatewayMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"agentID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"AgentCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"agentID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AgentFundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"ParaID\",\"name\":\"paraID\",\"type\":\"uint256\"}],\"name\":\"ChannelCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"ParaID\",\"name\":\"paraID\",\"type\":\"uint256\"}],\"name\":\"ChannelUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"ParaID\",\"name\":\"origin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"InboundMessageDispatched\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enumOperatingMode\",\"name\":\"mode\",\"type\":\"uint8\"}],\"name\":\"OperatingModeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"ParaID\",\"name\":\"destination\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"OutboundMessageAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"ParaID\",\"name\":\"destinationChain\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"destinationAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"}],\"name\":\"TokenSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"agentID\",\"type\":\"bytes32\"}],\"name\":\"agentOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ParaID\",\"name\":\"paraID\",\"type\":\"uint256\"}],\"name\":\"channelFeeRewardOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ParaID\",\"name\":\"paraID\",\"type\":\"uint256\"}],\"name\":\"channelNoncesOf\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ParaID\",\"name\":\"paraID\",\"type\":\"uint256\"}],\"name\":\"channelOperatingModeOf\",\"outputs\":[{\"internalType\":\"enumOperatingMode\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatingMode\",\"outputs\":[{\"internalType\":\"enumOperatingMode\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerToken\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"ParaID\",\"name\":\"destinationChain\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"destinationAddress\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"}],\"name\":\"sendToken\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"ParaID\",\"name\":\"destinationChain\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"amount\",\"type\":\"uint128\"}],\"name\":\"sendToken\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"ParaID\",\"name\":\"origin\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"enumCommand\",\"name\":\"command\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"params\",\"type\":\"bytes\"}],\"internalType\":\"structInboundMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"leafProof\",\"type\":\"bytes32[]\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"parentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"extrinsicsRoot\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"kind\",\"type\":\"uint256\"},{\"internalType\":\"bytes4\",\"name\":\"consensusEngineID\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structVerification.DigestItem[]\",\"name\":\"digestItems\",\"type\":\"tuple[]\"}],\"internalType\":\"structVerification.ParachainHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"pos\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"width\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structVerification.HeadProof\",\"name\":\"headProof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"parentNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"parentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structVerification.MMRLeafPartial\",\"name\":\"leafPartial\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"leafProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"leafProofOrder\",\"type\":\"uint256\"}],\"internalType\":\"structVerification.Proof\",\"name\":\"headerProof\",\"type\":\"tuple\"}],\"name\":\"submitInbound\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// GatewayABI is the input ABI used to generate the binding from. +// Deprecated: Use GatewayMetaData.ABI instead. +var GatewayABI = GatewayMetaData.ABI + +// Gateway is an auto generated Go binding around an Ethereum contract. +type Gateway struct { + GatewayCaller // Read-only binding to the contract + GatewayTransactor // Write-only binding to the contract + GatewayFilterer // Log filterer for contract events +} + +// GatewayCaller is an auto generated read-only Go binding around an Ethereum contract. +type GatewayCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// GatewayTransactor is an auto generated write-only Go binding around an Ethereum contract. +type GatewayTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// GatewayFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type GatewayFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// GatewaySession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type GatewaySession struct { + Contract *Gateway // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// GatewayCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type GatewayCallerSession struct { + Contract *GatewayCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// GatewayTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type GatewayTransactorSession struct { + Contract *GatewayTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// GatewayRaw is an auto generated low-level Go binding around an Ethereum contract. +type GatewayRaw struct { + Contract *Gateway // Generic contract binding to access the raw methods on +} + +// GatewayCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type GatewayCallerRaw struct { + Contract *GatewayCaller // Generic read-only contract binding to access the raw methods on +} + +// GatewayTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type GatewayTransactorRaw struct { + Contract *GatewayTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewGateway creates a new instance of Gateway, bound to a specific deployed contract. +func NewGateway(address common.Address, backend bind.ContractBackend) (*Gateway, error) { + contract, err := bindGateway(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Gateway{GatewayCaller: GatewayCaller{contract: contract}, GatewayTransactor: GatewayTransactor{contract: contract}, GatewayFilterer: GatewayFilterer{contract: contract}}, nil +} + +// NewGatewayCaller creates a new read-only instance of Gateway, bound to a specific deployed contract. +func NewGatewayCaller(address common.Address, caller bind.ContractCaller) (*GatewayCaller, error) { + contract, err := bindGateway(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &GatewayCaller{contract: contract}, nil +} + +// NewGatewayTransactor creates a new write-only instance of Gateway, bound to a specific deployed contract. +func NewGatewayTransactor(address common.Address, transactor bind.ContractTransactor) (*GatewayTransactor, error) { + contract, err := bindGateway(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &GatewayTransactor{contract: contract}, nil +} + +// NewGatewayFilterer creates a new log filterer instance of Gateway, bound to a specific deployed contract. +func NewGatewayFilterer(address common.Address, filterer bind.ContractFilterer) (*GatewayFilterer, error) { + contract, err := bindGateway(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &GatewayFilterer{contract: contract}, nil +} + +// bindGateway binds a generic wrapper to an already deployed contract. +func bindGateway(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := GatewayMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Gateway *GatewayRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Gateway.Contract.GatewayCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Gateway *GatewayRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Gateway.Contract.GatewayTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Gateway *GatewayRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Gateway.Contract.GatewayTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Gateway *GatewayCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Gateway.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Gateway *GatewayTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Gateway.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Gateway *GatewayTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Gateway.Contract.contract.Transact(opts, method, params...) +} + +// AgentOf is a free data retrieval call binding the contract method 0x5e6dae26. +// +// Solidity: function agentOf(bytes32 agentID) view returns(address) +func (_Gateway *GatewayCaller) AgentOf(opts *bind.CallOpts, agentID [32]byte) (common.Address, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "agentOf", agentID) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// AgentOf is a free data retrieval call binding the contract method 0x5e6dae26. +// +// Solidity: function agentOf(bytes32 agentID) view returns(address) +func (_Gateway *GatewaySession) AgentOf(agentID [32]byte) (common.Address, error) { + return _Gateway.Contract.AgentOf(&_Gateway.CallOpts, agentID) +} + +// AgentOf is a free data retrieval call binding the contract method 0x5e6dae26. +// +// Solidity: function agentOf(bytes32 agentID) view returns(address) +func (_Gateway *GatewayCallerSession) AgentOf(agentID [32]byte) (common.Address, error) { + return _Gateway.Contract.AgentOf(&_Gateway.CallOpts, agentID) +} + +// ChannelFeeRewardOf is a free data retrieval call binding the contract method 0xa029cc18. +// +// Solidity: function channelFeeRewardOf(uint256 paraID) view returns(uint256, uint256) +func (_Gateway *GatewayCaller) ChannelFeeRewardOf(opts *bind.CallOpts, paraID *big.Int) (*big.Int, *big.Int, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "channelFeeRewardOf", paraID) + + if err != nil { + return *new(*big.Int), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return out0, out1, err + +} + +// ChannelFeeRewardOf is a free data retrieval call binding the contract method 0xa029cc18. +// +// Solidity: function channelFeeRewardOf(uint256 paraID) view returns(uint256, uint256) +func (_Gateway *GatewaySession) ChannelFeeRewardOf(paraID *big.Int) (*big.Int, *big.Int, error) { + return _Gateway.Contract.ChannelFeeRewardOf(&_Gateway.CallOpts, paraID) +} + +// ChannelFeeRewardOf is a free data retrieval call binding the contract method 0xa029cc18. +// +// Solidity: function channelFeeRewardOf(uint256 paraID) view returns(uint256, uint256) +func (_Gateway *GatewayCallerSession) ChannelFeeRewardOf(paraID *big.Int) (*big.Int, *big.Int, error) { + return _Gateway.Contract.ChannelFeeRewardOf(&_Gateway.CallOpts, paraID) +} + +// ChannelNoncesOf is a free data retrieval call binding the contract method 0x821b8e3f. +// +// Solidity: function channelNoncesOf(uint256 paraID) view returns(uint64, uint64) +func (_Gateway *GatewayCaller) ChannelNoncesOf(opts *bind.CallOpts, paraID *big.Int) (uint64, uint64, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "channelNoncesOf", paraID) + + if err != nil { + return *new(uint64), *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + out1 := *abi.ConvertType(out[1], new(uint64)).(*uint64) + + return out0, out1, err + +} + +// ChannelNoncesOf is a free data retrieval call binding the contract method 0x821b8e3f. +// +// Solidity: function channelNoncesOf(uint256 paraID) view returns(uint64, uint64) +func (_Gateway *GatewaySession) ChannelNoncesOf(paraID *big.Int) (uint64, uint64, error) { + return _Gateway.Contract.ChannelNoncesOf(&_Gateway.CallOpts, paraID) +} + +// ChannelNoncesOf is a free data retrieval call binding the contract method 0x821b8e3f. +// +// Solidity: function channelNoncesOf(uint256 paraID) view returns(uint64, uint64) +func (_Gateway *GatewayCallerSession) ChannelNoncesOf(paraID *big.Int) (uint64, uint64, error) { + return _Gateway.Contract.ChannelNoncesOf(&_Gateway.CallOpts, paraID) +} + +// ChannelOperatingModeOf is a free data retrieval call binding the contract method 0xffbb2698. +// +// Solidity: function channelOperatingModeOf(uint256 paraID) view returns(uint8) +func (_Gateway *GatewayCaller) ChannelOperatingModeOf(opts *bind.CallOpts, paraID *big.Int) (uint8, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "channelOperatingModeOf", paraID) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// ChannelOperatingModeOf is a free data retrieval call binding the contract method 0xffbb2698. +// +// Solidity: function channelOperatingModeOf(uint256 paraID) view returns(uint8) +func (_Gateway *GatewaySession) ChannelOperatingModeOf(paraID *big.Int) (uint8, error) { + return _Gateway.Contract.ChannelOperatingModeOf(&_Gateway.CallOpts, paraID) +} + +// ChannelOperatingModeOf is a free data retrieval call binding the contract method 0xffbb2698. +// +// Solidity: function channelOperatingModeOf(uint256 paraID) view returns(uint8) +func (_Gateway *GatewayCallerSession) ChannelOperatingModeOf(paraID *big.Int) (uint8, error) { + return _Gateway.Contract.ChannelOperatingModeOf(&_Gateway.CallOpts, paraID) +} + +// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. +// +// Solidity: function implementation() view returns(address) +func (_Gateway *GatewayCaller) Implementation(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "implementation") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. +// +// Solidity: function implementation() view returns(address) +func (_Gateway *GatewaySession) Implementation() (common.Address, error) { + return _Gateway.Contract.Implementation(&_Gateway.CallOpts) +} + +// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. +// +// Solidity: function implementation() view returns(address) +func (_Gateway *GatewayCallerSession) Implementation() (common.Address, error) { + return _Gateway.Contract.Implementation(&_Gateway.CallOpts) +} + +// OperatingMode is a free data retrieval call binding the contract method 0x38004f69. +// +// Solidity: function operatingMode() view returns(uint8) +func (_Gateway *GatewayCaller) OperatingMode(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Gateway.contract.Call(opts, &out, "operatingMode") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// OperatingMode is a free data retrieval call binding the contract method 0x38004f69. +// +// Solidity: function operatingMode() view returns(uint8) +func (_Gateway *GatewaySession) OperatingMode() (uint8, error) { + return _Gateway.Contract.OperatingMode(&_Gateway.CallOpts) +} + +// OperatingMode is a free data retrieval call binding the contract method 0x38004f69. +// +// Solidity: function operatingMode() view returns(uint8) +func (_Gateway *GatewayCallerSession) OperatingMode() (uint8, error) { + return _Gateway.Contract.OperatingMode(&_Gateway.CallOpts) +} + +// RegisterToken is a paid mutator transaction binding the contract method 0x09824a80. +// +// Solidity: function registerToken(address token) payable returns() +func (_Gateway *GatewayTransactor) RegisterToken(opts *bind.TransactOpts, token common.Address) (*types.Transaction, error) { + return _Gateway.contract.Transact(opts, "registerToken", token) +} + +// RegisterToken is a paid mutator transaction binding the contract method 0x09824a80. +// +// Solidity: function registerToken(address token) payable returns() +func (_Gateway *GatewaySession) RegisterToken(token common.Address) (*types.Transaction, error) { + return _Gateway.Contract.RegisterToken(&_Gateway.TransactOpts, token) +} + +// RegisterToken is a paid mutator transaction binding the contract method 0x09824a80. +// +// Solidity: function registerToken(address token) payable returns() +func (_Gateway *GatewayTransactorSession) RegisterToken(token common.Address) (*types.Transaction, error) { + return _Gateway.Contract.RegisterToken(&_Gateway.TransactOpts, token) +} + +// SendToken is a paid mutator transaction binding the contract method 0x506acef5. +// +// Solidity: function sendToken(address token, uint256 destinationChain, bytes32 destinationAddress, uint128 amount) payable returns() +func (_Gateway *GatewayTransactor) SendToken(opts *bind.TransactOpts, token common.Address, destinationChain *big.Int, destinationAddress [32]byte, amount *big.Int) (*types.Transaction, error) { + return _Gateway.contract.Transact(opts, "sendToken", token, destinationChain, destinationAddress, amount) +} + +// SendToken is a paid mutator transaction binding the contract method 0x506acef5. +// +// Solidity: function sendToken(address token, uint256 destinationChain, bytes32 destinationAddress, uint128 amount) payable returns() +func (_Gateway *GatewaySession) SendToken(token common.Address, destinationChain *big.Int, destinationAddress [32]byte, amount *big.Int) (*types.Transaction, error) { + return _Gateway.Contract.SendToken(&_Gateway.TransactOpts, token, destinationChain, destinationAddress, amount) +} + +// SendToken is a paid mutator transaction binding the contract method 0x506acef5. +// +// Solidity: function sendToken(address token, uint256 destinationChain, bytes32 destinationAddress, uint128 amount) payable returns() +func (_Gateway *GatewayTransactorSession) SendToken(token common.Address, destinationChain *big.Int, destinationAddress [32]byte, amount *big.Int) (*types.Transaction, error) { + return _Gateway.Contract.SendToken(&_Gateway.TransactOpts, token, destinationChain, destinationAddress, amount) +} + +// SendToken0 is a paid mutator transaction binding the contract method 0x960897bf. +// +// Solidity: function sendToken(address token, uint256 destinationChain, address destinationAddress, uint128 amount) payable returns() +func (_Gateway *GatewayTransactor) SendToken0(opts *bind.TransactOpts, token common.Address, destinationChain *big.Int, destinationAddress common.Address, amount *big.Int) (*types.Transaction, error) { + return _Gateway.contract.Transact(opts, "sendToken0", token, destinationChain, destinationAddress, amount) +} + +// SendToken0 is a paid mutator transaction binding the contract method 0x960897bf. +// +// Solidity: function sendToken(address token, uint256 destinationChain, address destinationAddress, uint128 amount) payable returns() +func (_Gateway *GatewaySession) SendToken0(token common.Address, destinationChain *big.Int, destinationAddress common.Address, amount *big.Int) (*types.Transaction, error) { + return _Gateway.Contract.SendToken0(&_Gateway.TransactOpts, token, destinationChain, destinationAddress, amount) +} + +// SendToken0 is a paid mutator transaction binding the contract method 0x960897bf. +// +// Solidity: function sendToken(address token, uint256 destinationChain, address destinationAddress, uint128 amount) payable returns() +func (_Gateway *GatewayTransactorSession) SendToken0(token common.Address, destinationChain *big.Int, destinationAddress common.Address, amount *big.Int) (*types.Transaction, error) { + return _Gateway.Contract.SendToken0(&_Gateway.TransactOpts, token, destinationChain, destinationAddress, amount) +} + +// SubmitInbound is a paid mutator transaction binding the contract method 0x920ee69f. +// +// Solidity: function submitInbound((uint256,uint64,uint8,bytes) message, bytes32[] leafProof, ((bytes32,uint256,bytes32,bytes32,(uint256,bytes4,bytes)[]),(uint256,uint256,bytes32[]),(uint8,uint32,bytes32,uint64,uint32,bytes32),bytes32[],uint256) headerProof) returns() +func (_Gateway *GatewayTransactor) SubmitInbound(opts *bind.TransactOpts, message InboundMessage, leafProof [][32]byte, headerProof VerificationProof) (*types.Transaction, error) { + return _Gateway.contract.Transact(opts, "submitInbound", message, leafProof, headerProof) +} + +// SubmitInbound is a paid mutator transaction binding the contract method 0x920ee69f. +// +// Solidity: function submitInbound((uint256,uint64,uint8,bytes) message, bytes32[] leafProof, ((bytes32,uint256,bytes32,bytes32,(uint256,bytes4,bytes)[]),(uint256,uint256,bytes32[]),(uint8,uint32,bytes32,uint64,uint32,bytes32),bytes32[],uint256) headerProof) returns() +func (_Gateway *GatewaySession) SubmitInbound(message InboundMessage, leafProof [][32]byte, headerProof VerificationProof) (*types.Transaction, error) { + return _Gateway.Contract.SubmitInbound(&_Gateway.TransactOpts, message, leafProof, headerProof) +} + +// SubmitInbound is a paid mutator transaction binding the contract method 0x920ee69f. +// +// Solidity: function submitInbound((uint256,uint64,uint8,bytes) message, bytes32[] leafProof, ((bytes32,uint256,bytes32,bytes32,(uint256,bytes4,bytes)[]),(uint256,uint256,bytes32[]),(uint8,uint32,bytes32,uint64,uint32,bytes32),bytes32[],uint256) headerProof) returns() +func (_Gateway *GatewayTransactorSession) SubmitInbound(message InboundMessage, leafProof [][32]byte, headerProof VerificationProof) (*types.Transaction, error) { + return _Gateway.Contract.SubmitInbound(&_Gateway.TransactOpts, message, leafProof, headerProof) +} + +// GatewayAgentCreatedIterator is returned from FilterAgentCreated and is used to iterate over the raw logs and unpacked data for AgentCreated events raised by the Gateway contract. +type GatewayAgentCreatedIterator struct { + Event *GatewayAgentCreated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayAgentCreatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayAgentCreated) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayAgentCreated) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayAgentCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayAgentCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayAgentCreated represents a AgentCreated event raised by the Gateway contract. +type GatewayAgentCreated struct { + AgentID [32]byte + Agent common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAgentCreated is a free log retrieval operation binding the contract event 0x7c96960a1ebd8cc753b10836ea25bd7c9c4f8cd43590db1e8b3648cb0ec4cc89. +// +// Solidity: event AgentCreated(bytes32 agentID, address agent) +func (_Gateway *GatewayFilterer) FilterAgentCreated(opts *bind.FilterOpts) (*GatewayAgentCreatedIterator, error) { + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "AgentCreated") + if err != nil { + return nil, err + } + return &GatewayAgentCreatedIterator{contract: _Gateway.contract, event: "AgentCreated", logs: logs, sub: sub}, nil +} + +// WatchAgentCreated is a free log subscription operation binding the contract event 0x7c96960a1ebd8cc753b10836ea25bd7c9c4f8cd43590db1e8b3648cb0ec4cc89. +// +// Solidity: event AgentCreated(bytes32 agentID, address agent) +func (_Gateway *GatewayFilterer) WatchAgentCreated(opts *bind.WatchOpts, sink chan<- *GatewayAgentCreated) (event.Subscription, error) { + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "AgentCreated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayAgentCreated) + if err := _Gateway.contract.UnpackLog(event, "AgentCreated", 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 +} + +// ParseAgentCreated is a log parse operation binding the contract event 0x7c96960a1ebd8cc753b10836ea25bd7c9c4f8cd43590db1e8b3648cb0ec4cc89. +// +// Solidity: event AgentCreated(bytes32 agentID, address agent) +func (_Gateway *GatewayFilterer) ParseAgentCreated(log types.Log) (*GatewayAgentCreated, error) { + event := new(GatewayAgentCreated) + if err := _Gateway.contract.UnpackLog(event, "AgentCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayAgentFundsWithdrawnIterator is returned from FilterAgentFundsWithdrawn and is used to iterate over the raw logs and unpacked data for AgentFundsWithdrawn events raised by the Gateway contract. +type GatewayAgentFundsWithdrawnIterator struct { + Event *GatewayAgentFundsWithdrawn // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayAgentFundsWithdrawnIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayAgentFundsWithdrawn) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayAgentFundsWithdrawn) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayAgentFundsWithdrawnIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayAgentFundsWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayAgentFundsWithdrawn represents a AgentFundsWithdrawn event raised by the Gateway contract. +type GatewayAgentFundsWithdrawn struct { + AgentID [32]byte + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAgentFundsWithdrawn is a free log retrieval operation binding the contract event 0xf953871855f78d5ccdd6268f2d9d69fc67f26542a35d2bba1c615521aed57054. +// +// Solidity: event AgentFundsWithdrawn(bytes32 indexed agentID, address indexed recipient, uint256 amount) +func (_Gateway *GatewayFilterer) FilterAgentFundsWithdrawn(opts *bind.FilterOpts, agentID [][32]byte, recipient []common.Address) (*GatewayAgentFundsWithdrawnIterator, error) { + + var agentIDRule []interface{} + for _, agentIDItem := range agentID { + agentIDRule = append(agentIDRule, agentIDItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "AgentFundsWithdrawn", agentIDRule, recipientRule) + if err != nil { + return nil, err + } + return &GatewayAgentFundsWithdrawnIterator{contract: _Gateway.contract, event: "AgentFundsWithdrawn", logs: logs, sub: sub}, nil +} + +// WatchAgentFundsWithdrawn is a free log subscription operation binding the contract event 0xf953871855f78d5ccdd6268f2d9d69fc67f26542a35d2bba1c615521aed57054. +// +// Solidity: event AgentFundsWithdrawn(bytes32 indexed agentID, address indexed recipient, uint256 amount) +func (_Gateway *GatewayFilterer) WatchAgentFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *GatewayAgentFundsWithdrawn, agentID [][32]byte, recipient []common.Address) (event.Subscription, error) { + + var agentIDRule []interface{} + for _, agentIDItem := range agentID { + agentIDRule = append(agentIDRule, agentIDItem) + } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "AgentFundsWithdrawn", agentIDRule, recipientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayAgentFundsWithdrawn) + if err := _Gateway.contract.UnpackLog(event, "AgentFundsWithdrawn", 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 +} + +// ParseAgentFundsWithdrawn is a log parse operation binding the contract event 0xf953871855f78d5ccdd6268f2d9d69fc67f26542a35d2bba1c615521aed57054. +// +// Solidity: event AgentFundsWithdrawn(bytes32 indexed agentID, address indexed recipient, uint256 amount) +func (_Gateway *GatewayFilterer) ParseAgentFundsWithdrawn(log types.Log) (*GatewayAgentFundsWithdrawn, error) { + event := new(GatewayAgentFundsWithdrawn) + if err := _Gateway.contract.UnpackLog(event, "AgentFundsWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayChannelCreatedIterator is returned from FilterChannelCreated and is used to iterate over the raw logs and unpacked data for ChannelCreated events raised by the Gateway contract. +type GatewayChannelCreatedIterator struct { + Event *GatewayChannelCreated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayChannelCreatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayChannelCreated) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayChannelCreated) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayChannelCreatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayChannelCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayChannelCreated represents a ChannelCreated event raised by the Gateway contract. +type GatewayChannelCreated struct { + ParaID *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChannelCreated is a free log retrieval operation binding the contract event 0xcd2f05e3ff25243d7bd719b28c9ae449c45126193d67a065cb4a94894c6704f2. +// +// Solidity: event ChannelCreated(uint256 indexed paraID) +func (_Gateway *GatewayFilterer) FilterChannelCreated(opts *bind.FilterOpts, paraID []*big.Int) (*GatewayChannelCreatedIterator, error) { + + var paraIDRule []interface{} + for _, paraIDItem := range paraID { + paraIDRule = append(paraIDRule, paraIDItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "ChannelCreated", paraIDRule) + if err != nil { + return nil, err + } + return &GatewayChannelCreatedIterator{contract: _Gateway.contract, event: "ChannelCreated", logs: logs, sub: sub}, nil +} + +// WatchChannelCreated is a free log subscription operation binding the contract event 0xcd2f05e3ff25243d7bd719b28c9ae449c45126193d67a065cb4a94894c6704f2. +// +// Solidity: event ChannelCreated(uint256 indexed paraID) +func (_Gateway *GatewayFilterer) WatchChannelCreated(opts *bind.WatchOpts, sink chan<- *GatewayChannelCreated, paraID []*big.Int) (event.Subscription, error) { + + var paraIDRule []interface{} + for _, paraIDItem := range paraID { + paraIDRule = append(paraIDRule, paraIDItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "ChannelCreated", paraIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayChannelCreated) + if err := _Gateway.contract.UnpackLog(event, "ChannelCreated", 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 +} + +// ParseChannelCreated is a log parse operation binding the contract event 0xcd2f05e3ff25243d7bd719b28c9ae449c45126193d67a065cb4a94894c6704f2. +// +// Solidity: event ChannelCreated(uint256 indexed paraID) +func (_Gateway *GatewayFilterer) ParseChannelCreated(log types.Log) (*GatewayChannelCreated, error) { + event := new(GatewayChannelCreated) + if err := _Gateway.contract.UnpackLog(event, "ChannelCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayChannelUpdatedIterator is returned from FilterChannelUpdated and is used to iterate over the raw logs and unpacked data for ChannelUpdated events raised by the Gateway contract. +type GatewayChannelUpdatedIterator struct { + Event *GatewayChannelUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayChannelUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayChannelUpdated) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayChannelUpdated) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayChannelUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayChannelUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayChannelUpdated represents a ChannelUpdated event raised by the Gateway contract. +type GatewayChannelUpdated struct { + ParaID *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChannelUpdated is a free log retrieval operation binding the contract event 0x1ff1603b88e71eb3560ca9cd0a1cbc6cf2947baa2df2b9aae7457ed3d96ca1c6. +// +// Solidity: event ChannelUpdated(uint256 indexed paraID) +func (_Gateway *GatewayFilterer) FilterChannelUpdated(opts *bind.FilterOpts, paraID []*big.Int) (*GatewayChannelUpdatedIterator, error) { + + var paraIDRule []interface{} + for _, paraIDItem := range paraID { + paraIDRule = append(paraIDRule, paraIDItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "ChannelUpdated", paraIDRule) + if err != nil { + return nil, err + } + return &GatewayChannelUpdatedIterator{contract: _Gateway.contract, event: "ChannelUpdated", logs: logs, sub: sub}, nil +} + +// WatchChannelUpdated is a free log subscription operation binding the contract event 0x1ff1603b88e71eb3560ca9cd0a1cbc6cf2947baa2df2b9aae7457ed3d96ca1c6. +// +// Solidity: event ChannelUpdated(uint256 indexed paraID) +func (_Gateway *GatewayFilterer) WatchChannelUpdated(opts *bind.WatchOpts, sink chan<- *GatewayChannelUpdated, paraID []*big.Int) (event.Subscription, error) { + + var paraIDRule []interface{} + for _, paraIDItem := range paraID { + paraIDRule = append(paraIDRule, paraIDItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "ChannelUpdated", paraIDRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayChannelUpdated) + if err := _Gateway.contract.UnpackLog(event, "ChannelUpdated", 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 +} + +// ParseChannelUpdated is a log parse operation binding the contract event 0x1ff1603b88e71eb3560ca9cd0a1cbc6cf2947baa2df2b9aae7457ed3d96ca1c6. +// +// Solidity: event ChannelUpdated(uint256 indexed paraID) +func (_Gateway *GatewayFilterer) ParseChannelUpdated(log types.Log) (*GatewayChannelUpdated, error) { + event := new(GatewayChannelUpdated) + if err := _Gateway.contract.UnpackLog(event, "ChannelUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayInboundMessageDispatchedIterator is returned from FilterInboundMessageDispatched and is used to iterate over the raw logs and unpacked data for InboundMessageDispatched events raised by the Gateway contract. +type GatewayInboundMessageDispatchedIterator struct { + Event *GatewayInboundMessageDispatched // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayInboundMessageDispatchedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayInboundMessageDispatched) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayInboundMessageDispatched) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayInboundMessageDispatchedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayInboundMessageDispatchedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayInboundMessageDispatched represents a InboundMessageDispatched event raised by the Gateway contract. +type GatewayInboundMessageDispatched struct { + Origin *big.Int + Nonce uint64 + Success bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInboundMessageDispatched is a free log retrieval operation binding the contract event 0xc413674585e5f4244fd69ce2c9587aac57f3fdaf6b337a1f39317d2ffa1279f1. +// +// Solidity: event InboundMessageDispatched(uint256 indexed origin, uint64 nonce, bool success) +func (_Gateway *GatewayFilterer) FilterInboundMessageDispatched(opts *bind.FilterOpts, origin []*big.Int) (*GatewayInboundMessageDispatchedIterator, error) { + + var originRule []interface{} + for _, originItem := range origin { + originRule = append(originRule, originItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "InboundMessageDispatched", originRule) + if err != nil { + return nil, err + } + return &GatewayInboundMessageDispatchedIterator{contract: _Gateway.contract, event: "InboundMessageDispatched", logs: logs, sub: sub}, nil +} + +// WatchInboundMessageDispatched is a free log subscription operation binding the contract event 0xc413674585e5f4244fd69ce2c9587aac57f3fdaf6b337a1f39317d2ffa1279f1. +// +// Solidity: event InboundMessageDispatched(uint256 indexed origin, uint64 nonce, bool success) +func (_Gateway *GatewayFilterer) WatchInboundMessageDispatched(opts *bind.WatchOpts, sink chan<- *GatewayInboundMessageDispatched, origin []*big.Int) (event.Subscription, error) { + + var originRule []interface{} + for _, originItem := range origin { + originRule = append(originRule, originItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "InboundMessageDispatched", originRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayInboundMessageDispatched) + if err := _Gateway.contract.UnpackLog(event, "InboundMessageDispatched", 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 +} + +// ParseInboundMessageDispatched is a log parse operation binding the contract event 0xc413674585e5f4244fd69ce2c9587aac57f3fdaf6b337a1f39317d2ffa1279f1. +// +// Solidity: event InboundMessageDispatched(uint256 indexed origin, uint64 nonce, bool success) +func (_Gateway *GatewayFilterer) ParseInboundMessageDispatched(log types.Log) (*GatewayInboundMessageDispatched, error) { + event := new(GatewayInboundMessageDispatched) + if err := _Gateway.contract.UnpackLog(event, "InboundMessageDispatched", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayOperatingModeChangedIterator is returned from FilterOperatingModeChanged and is used to iterate over the raw logs and unpacked data for OperatingModeChanged events raised by the Gateway contract. +type GatewayOperatingModeChangedIterator struct { + Event *GatewayOperatingModeChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayOperatingModeChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayOperatingModeChanged) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayOperatingModeChanged) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayOperatingModeChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayOperatingModeChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayOperatingModeChanged represents a OperatingModeChanged event raised by the Gateway contract. +type GatewayOperatingModeChanged struct { + Mode uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOperatingModeChanged is a free log retrieval operation binding the contract event 0x4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a. +// +// Solidity: event OperatingModeChanged(uint8 mode) +func (_Gateway *GatewayFilterer) FilterOperatingModeChanged(opts *bind.FilterOpts) (*GatewayOperatingModeChangedIterator, error) { + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "OperatingModeChanged") + if err != nil { + return nil, err + } + return &GatewayOperatingModeChangedIterator{contract: _Gateway.contract, event: "OperatingModeChanged", logs: logs, sub: sub}, nil +} + +// WatchOperatingModeChanged is a free log subscription operation binding the contract event 0x4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a. +// +// Solidity: event OperatingModeChanged(uint8 mode) +func (_Gateway *GatewayFilterer) WatchOperatingModeChanged(opts *bind.WatchOpts, sink chan<- *GatewayOperatingModeChanged) (event.Subscription, error) { + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "OperatingModeChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayOperatingModeChanged) + if err := _Gateway.contract.UnpackLog(event, "OperatingModeChanged", 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 +} + +// ParseOperatingModeChanged is a log parse operation binding the contract event 0x4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a. +// +// Solidity: event OperatingModeChanged(uint8 mode) +func (_Gateway *GatewayFilterer) ParseOperatingModeChanged(log types.Log) (*GatewayOperatingModeChanged, error) { + event := new(GatewayOperatingModeChanged) + if err := _Gateway.contract.UnpackLog(event, "OperatingModeChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayOutboundMessageAcceptedIterator is returned from FilterOutboundMessageAccepted and is used to iterate over the raw logs and unpacked data for OutboundMessageAccepted events raised by the Gateway contract. +type GatewayOutboundMessageAcceptedIterator struct { + Event *GatewayOutboundMessageAccepted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayOutboundMessageAcceptedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayOutboundMessageAccepted) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayOutboundMessageAccepted) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayOutboundMessageAcceptedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayOutboundMessageAcceptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayOutboundMessageAccepted represents a OutboundMessageAccepted event raised by the Gateway contract. +type GatewayOutboundMessageAccepted struct { + Destination *big.Int + Nonce uint64 + Payload []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOutboundMessageAccepted is a free log retrieval operation binding the contract event 0xd56f1b8dfd3ba41f19c499ceec5f9546f61befa5f10398a75d7dba53a219fece. +// +// Solidity: event OutboundMessageAccepted(uint256 indexed destination, uint64 nonce, bytes payload) +func (_Gateway *GatewayFilterer) FilterOutboundMessageAccepted(opts *bind.FilterOpts, destination []*big.Int) (*GatewayOutboundMessageAcceptedIterator, error) { + + var destinationRule []interface{} + for _, destinationItem := range destination { + destinationRule = append(destinationRule, destinationItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "OutboundMessageAccepted", destinationRule) + if err != nil { + return nil, err + } + return &GatewayOutboundMessageAcceptedIterator{contract: _Gateway.contract, event: "OutboundMessageAccepted", logs: logs, sub: sub}, nil +} + +// WatchOutboundMessageAccepted is a free log subscription operation binding the contract event 0xd56f1b8dfd3ba41f19c499ceec5f9546f61befa5f10398a75d7dba53a219fece. +// +// Solidity: event OutboundMessageAccepted(uint256 indexed destination, uint64 nonce, bytes payload) +func (_Gateway *GatewayFilterer) WatchOutboundMessageAccepted(opts *bind.WatchOpts, sink chan<- *GatewayOutboundMessageAccepted, destination []*big.Int) (event.Subscription, error) { + + var destinationRule []interface{} + for _, destinationItem := range destination { + destinationRule = append(destinationRule, destinationItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "OutboundMessageAccepted", destinationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayOutboundMessageAccepted) + if err := _Gateway.contract.UnpackLog(event, "OutboundMessageAccepted", 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 +} + +// ParseOutboundMessageAccepted is a log parse operation binding the contract event 0xd56f1b8dfd3ba41f19c499ceec5f9546f61befa5f10398a75d7dba53a219fece. +// +// Solidity: event OutboundMessageAccepted(uint256 indexed destination, uint64 nonce, bytes payload) +func (_Gateway *GatewayFilterer) ParseOutboundMessageAccepted(log types.Log) (*GatewayOutboundMessageAccepted, error) { + event := new(GatewayOutboundMessageAccepted) + if err := _Gateway.contract.UnpackLog(event, "OutboundMessageAccepted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayTokenRegisteredIterator is returned from FilterTokenRegistered and is used to iterate over the raw logs and unpacked data for TokenRegistered events raised by the Gateway contract. +type GatewayTokenRegisteredIterator struct { + Event *GatewayTokenRegistered // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayTokenRegisteredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayTokenRegistered) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayTokenRegistered) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayTokenRegisteredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayTokenRegisteredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayTokenRegistered represents a TokenRegistered event raised by the Gateway contract. +type GatewayTokenRegistered struct { + Token common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTokenRegistered is a free log retrieval operation binding the contract event 0x158412daecdc1456d01568828bcdb18464cc7f1ce0215ddbc3f3cfede9d1e63d. +// +// Solidity: event TokenRegistered(address token) +func (_Gateway *GatewayFilterer) FilterTokenRegistered(opts *bind.FilterOpts) (*GatewayTokenRegisteredIterator, error) { + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "TokenRegistered") + if err != nil { + return nil, err + } + return &GatewayTokenRegisteredIterator{contract: _Gateway.contract, event: "TokenRegistered", logs: logs, sub: sub}, nil +} + +// WatchTokenRegistered is a free log subscription operation binding the contract event 0x158412daecdc1456d01568828bcdb18464cc7f1ce0215ddbc3f3cfede9d1e63d. +// +// Solidity: event TokenRegistered(address token) +func (_Gateway *GatewayFilterer) WatchTokenRegistered(opts *bind.WatchOpts, sink chan<- *GatewayTokenRegistered) (event.Subscription, error) { + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "TokenRegistered") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayTokenRegistered) + if err := _Gateway.contract.UnpackLog(event, "TokenRegistered", 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 +} + +// ParseTokenRegistered is a log parse operation binding the contract event 0x158412daecdc1456d01568828bcdb18464cc7f1ce0215ddbc3f3cfede9d1e63d. +// +// Solidity: event TokenRegistered(address token) +func (_Gateway *GatewayFilterer) ParseTokenRegistered(log types.Log) (*GatewayTokenRegistered, error) { + event := new(GatewayTokenRegistered) + if err := _Gateway.contract.UnpackLog(event, "TokenRegistered", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayTokenSentIterator is returned from FilterTokenSent and is used to iterate over the raw logs and unpacked data for TokenSent events raised by the Gateway contract. +type GatewayTokenSentIterator struct { + Event *GatewayTokenSent // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayTokenSentIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayTokenSent) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayTokenSent) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayTokenSentIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayTokenSentIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayTokenSent represents a TokenSent event raised by the Gateway contract. +type GatewayTokenSent struct { + Token common.Address + DestinationChain *big.Int + DestinationAddress []byte + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTokenSent is a free log retrieval operation binding the contract event 0xe1ae29e81ebd3cc6a74fb91c2d9f33e3d80313f1d106f2b24e62cac4bfc86d98. +// +// Solidity: event TokenSent(address token, uint256 destinationChain, bytes destinationAddress, uint128 amount) +func (_Gateway *GatewayFilterer) FilterTokenSent(opts *bind.FilterOpts) (*GatewayTokenSentIterator, error) { + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "TokenSent") + if err != nil { + return nil, err + } + return &GatewayTokenSentIterator{contract: _Gateway.contract, event: "TokenSent", logs: logs, sub: sub}, nil +} + +// WatchTokenSent is a free log subscription operation binding the contract event 0xe1ae29e81ebd3cc6a74fb91c2d9f33e3d80313f1d106f2b24e62cac4bfc86d98. +// +// Solidity: event TokenSent(address token, uint256 destinationChain, bytes destinationAddress, uint128 amount) +func (_Gateway *GatewayFilterer) WatchTokenSent(opts *bind.WatchOpts, sink chan<- *GatewayTokenSent) (event.Subscription, error) { + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "TokenSent") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayTokenSent) + if err := _Gateway.contract.UnpackLog(event, "TokenSent", 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 +} + +// ParseTokenSent is a log parse operation binding the contract event 0xe1ae29e81ebd3cc6a74fb91c2d9f33e3d80313f1d106f2b24e62cac4bfc86d98. +// +// Solidity: event TokenSent(address token, uint256 destinationChain, bytes destinationAddress, uint128 amount) +func (_Gateway *GatewayFilterer) ParseTokenSent(log types.Log) (*GatewayTokenSent, error) { + event := new(GatewayTokenSent) + if err := _Gateway.contract.UnpackLog(event, "TokenSent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GatewayUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the Gateway contract. +type GatewayUpgradedIterator struct { + Event *GatewayUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GatewayUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GatewayUpgraded) + 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 + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GatewayUpgraded) + 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() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GatewayUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GatewayUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GatewayUpgraded represents a Upgraded event raised by the Gateway contract. +type GatewayUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Gateway *GatewayFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*GatewayUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _Gateway.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &GatewayUpgradedIterator{contract: _Gateway.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Gateway *GatewayFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *GatewayUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _Gateway.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GatewayUpgraded) + if err := _Gateway.contract.UnpackLog(event, "Upgraded", 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 +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_Gateway *GatewayFilterer) ParseUpgraded(log types.Log) (*GatewayUpgraded, error) { + event := new(GatewayUpgraded) + if err := _Gateway.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/relayer/contracts/generate.go b/relayer/contracts/generate.go index e351410711d77..b9ac5e863320d 100644 --- a/relayer/contracts/generate.go +++ b/relayer/contracts/generate.go @@ -1,6 +1,4 @@ -//go:generate bash -c "jq .abi ../../core/packages/contracts/out/OpaqueProof.sol/OpaqueProof.json | abigen --abi - --type OpaqueProof --pkg contracts --out opaque_proof.go" -//go:generate bash -c "jq .abi ../../core/packages/contracts/out/BeefyClient.sol/BeefyClient.json | abigen --abi - --type BeefyClient --pkg contracts --out beefy_client.go" -//go:generate bash -c "jq .abi ../../core/packages/contracts/out/InboundQueue.sol/InboundQueue.json | abigen --abi - --type InboundQueue --pkg contracts --out inbound_queue.go" -//go:generate bash -c "jq .abi ../../core/packages/contracts/out/OutboundQueue.sol/OutboundQueue.json | abigen --abi - --type OutboundQueue --pkg contracts --out outbound_queue.go" +//go:generate bash -c "jq .abi ../../contracts/out/BeefyClient.sol/BeefyClient.json | abigen --abi - --type BeefyClient --pkg contracts --out beefy_client.go" +//go:generate bash -c "jq .abi ../../contracts/out/IGateway.sol/IGateway.json | abigen --abi - --type Gateway --pkg contracts --out gateway.go" package contracts diff --git a/relayer/contracts/inbound_queue.go b/relayer/contracts/inbound_queue.go deleted file mode 100644 index eb60ca1b92f6f..0000000000000 --- a/relayer/contracts/inbound_queue.go +++ /dev/null @@ -1,2113 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contracts - -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" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// InboundQueueMessage is an auto generated low-level Go binding around an user-defined struct. -type InboundQueueMessage struct { - Origin uint32 - Nonce uint64 - Recipient [32]byte - Payload []byte -} - -// InboundQueueMetaData contains all meta data concerning the InboundQueue contract. -var InboundQueueMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIParachainClient\",\"name\":\"_parachainClient\",\"type\":\"address\"},{\"internalType\":\"contractVault\",\"name\":\"_vault\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_reward\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LookupError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughGas\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasToForward\",\"type\":\"uint256\"}],\"name\":\"GasToForwardUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"id\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"contractIRecipient\",\"name\":\"handler\",\"type\":\"address\"}],\"name\":\"HandlerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"}],\"name\":\"InvalidRecipient\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"ParaID\",\"name\":\"origin\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"enumInboundQueue.DispatchResult\",\"name\":\"result\",\"type\":\"uint8\"}],\"name\":\"MessageDispatched\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"parachainClient\",\"type\":\"address\"}],\"name\":\"ParachainClientUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"name\":\"RewardUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vault\",\"type\":\"address\"}],\"name\":\"VaultUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GAS_BUFFER\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasToForward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ParaID\",\"name\":\"origin\",\"type\":\"uint32\"}],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"parachainClient\",\"outputs\":[{\"internalType\":\"contractIParachainClient\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"contractRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"reward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"ParaID\",\"name\":\"origin\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"internalType\":\"structInboundQueue.Message\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"leafProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"headerProof\",\"type\":\"bytes\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_gasToForward\",\"type\":\"uint256\"}],\"name\":\"updateGasToForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_reward\",\"type\":\"uint256\"}],\"name\":\"updateReward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vault\",\"outputs\":[{\"internalType\":\"contractVault\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", -} - -// InboundQueueABI is the input ABI used to generate the binding from. -// Deprecated: Use InboundQueueMetaData.ABI instead. -var InboundQueueABI = InboundQueueMetaData.ABI - -// InboundQueue is an auto generated Go binding around an Ethereum contract. -type InboundQueue struct { - InboundQueueCaller // Read-only binding to the contract - InboundQueueTransactor // Write-only binding to the contract - InboundQueueFilterer // Log filterer for contract events -} - -// InboundQueueCaller is an auto generated read-only Go binding around an Ethereum contract. -type InboundQueueCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// InboundQueueTransactor is an auto generated write-only Go binding around an Ethereum contract. -type InboundQueueTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// InboundQueueFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type InboundQueueFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// InboundQueueSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type InboundQueueSession struct { - Contract *InboundQueue // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// InboundQueueCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type InboundQueueCallerSession struct { - Contract *InboundQueueCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// InboundQueueTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type InboundQueueTransactorSession struct { - Contract *InboundQueueTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// InboundQueueRaw is an auto generated low-level Go binding around an Ethereum contract. -type InboundQueueRaw struct { - Contract *InboundQueue // Generic contract binding to access the raw methods on -} - -// InboundQueueCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type InboundQueueCallerRaw struct { - Contract *InboundQueueCaller // Generic read-only contract binding to access the raw methods on -} - -// InboundQueueTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type InboundQueueTransactorRaw struct { - Contract *InboundQueueTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewInboundQueue creates a new instance of InboundQueue, bound to a specific deployed contract. -func NewInboundQueue(address common.Address, backend bind.ContractBackend) (*InboundQueue, error) { - contract, err := bindInboundQueue(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &InboundQueue{InboundQueueCaller: InboundQueueCaller{contract: contract}, InboundQueueTransactor: InboundQueueTransactor{contract: contract}, InboundQueueFilterer: InboundQueueFilterer{contract: contract}}, nil -} - -// NewInboundQueueCaller creates a new read-only instance of InboundQueue, bound to a specific deployed contract. -func NewInboundQueueCaller(address common.Address, caller bind.ContractCaller) (*InboundQueueCaller, error) { - contract, err := bindInboundQueue(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &InboundQueueCaller{contract: contract}, nil -} - -// NewInboundQueueTransactor creates a new write-only instance of InboundQueue, bound to a specific deployed contract. -func NewInboundQueueTransactor(address common.Address, transactor bind.ContractTransactor) (*InboundQueueTransactor, error) { - contract, err := bindInboundQueue(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &InboundQueueTransactor{contract: contract}, nil -} - -// NewInboundQueueFilterer creates a new log filterer instance of InboundQueue, bound to a specific deployed contract. -func NewInboundQueueFilterer(address common.Address, filterer bind.ContractFilterer) (*InboundQueueFilterer, error) { - contract, err := bindInboundQueue(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &InboundQueueFilterer{contract: contract}, nil -} - -// bindInboundQueue binds a generic wrapper to an already deployed contract. -func bindInboundQueue(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(InboundQueueABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_InboundQueue *InboundQueueRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _InboundQueue.Contract.InboundQueueCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_InboundQueue *InboundQueueRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _InboundQueue.Contract.InboundQueueTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_InboundQueue *InboundQueueRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _InboundQueue.Contract.InboundQueueTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_InboundQueue *InboundQueueCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _InboundQueue.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_InboundQueue *InboundQueueTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _InboundQueue.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_InboundQueue *InboundQueueTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _InboundQueue.Contract.contract.Transact(opts, method, params...) -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_InboundQueue *InboundQueueCaller) ADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_InboundQueue *InboundQueueSession) ADMINROLE() ([32]byte, error) { - return _InboundQueue.Contract.ADMINROLE(&_InboundQueue.CallOpts) -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_InboundQueue *InboundQueueCallerSession) ADMINROLE() ([32]byte, error) { - return _InboundQueue.Contract.ADMINROLE(&_InboundQueue.CallOpts) -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_InboundQueue *InboundQueueCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_InboundQueue *InboundQueueSession) DEFAULTADMINROLE() ([32]byte, error) { - return _InboundQueue.Contract.DEFAULTADMINROLE(&_InboundQueue.CallOpts) -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_InboundQueue *InboundQueueCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _InboundQueue.Contract.DEFAULTADMINROLE(&_InboundQueue.CallOpts) -} - -// GASBUFFER is a free data retrieval call binding the contract method 0xc7e67360. -// -// Solidity: function GAS_BUFFER() view returns(uint256) -func (_InboundQueue *InboundQueueCaller) GASBUFFER(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "GAS_BUFFER") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GASBUFFER is a free data retrieval call binding the contract method 0xc7e67360. -// -// Solidity: function GAS_BUFFER() view returns(uint256) -func (_InboundQueue *InboundQueueSession) GASBUFFER() (*big.Int, error) { - return _InboundQueue.Contract.GASBUFFER(&_InboundQueue.CallOpts) -} - -// GASBUFFER is a free data retrieval call binding the contract method 0xc7e67360. -// -// Solidity: function GAS_BUFFER() view returns(uint256) -func (_InboundQueue *InboundQueueCallerSession) GASBUFFER() (*big.Int, error) { - return _InboundQueue.Contract.GASBUFFER(&_InboundQueue.CallOpts) -} - -// GasToForward is a free data retrieval call binding the contract method 0x3b834210. -// -// Solidity: function gasToForward() view returns(uint256) -func (_InboundQueue *InboundQueueCaller) GasToForward(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "gasToForward") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GasToForward is a free data retrieval call binding the contract method 0x3b834210. -// -// Solidity: function gasToForward() view returns(uint256) -func (_InboundQueue *InboundQueueSession) GasToForward() (*big.Int, error) { - return _InboundQueue.Contract.GasToForward(&_InboundQueue.CallOpts) -} - -// GasToForward is a free data retrieval call binding the contract method 0x3b834210. -// -// Solidity: function gasToForward() view returns(uint256) -func (_InboundQueue *InboundQueueCallerSession) GasToForward() (*big.Int, error) { - return _InboundQueue.Contract.GasToForward(&_InboundQueue.CallOpts) -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_InboundQueue *InboundQueueCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "getRoleAdmin", role) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_InboundQueue *InboundQueueSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _InboundQueue.Contract.GetRoleAdmin(&_InboundQueue.CallOpts, role) -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_InboundQueue *InboundQueueCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _InboundQueue.Contract.GetRoleAdmin(&_InboundQueue.CallOpts, role) -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_InboundQueue *InboundQueueCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "hasRole", role, account) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_InboundQueue *InboundQueueSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _InboundQueue.Contract.HasRole(&_InboundQueue.CallOpts, role, account) -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_InboundQueue *InboundQueueCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _InboundQueue.Contract.HasRole(&_InboundQueue.CallOpts, role, account) -} - -// Nonce is a free data retrieval call binding the contract method 0x141c4985. -// -// Solidity: function nonce(uint32 origin) view returns(uint64) -func (_InboundQueue *InboundQueueCaller) Nonce(opts *bind.CallOpts, origin uint32) (uint64, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "nonce", origin) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// Nonce is a free data retrieval call binding the contract method 0x141c4985. -// -// Solidity: function nonce(uint32 origin) view returns(uint64) -func (_InboundQueue *InboundQueueSession) Nonce(origin uint32) (uint64, error) { - return _InboundQueue.Contract.Nonce(&_InboundQueue.CallOpts, origin) -} - -// Nonce is a free data retrieval call binding the contract method 0x141c4985. -// -// Solidity: function nonce(uint32 origin) view returns(uint64) -func (_InboundQueue *InboundQueueCallerSession) Nonce(origin uint32) (uint64, error) { - return _InboundQueue.Contract.Nonce(&_InboundQueue.CallOpts, origin) -} - -// ParachainClient is a free data retrieval call binding the contract method 0x1674f9b7. -// -// Solidity: function parachainClient() view returns(address) -func (_InboundQueue *InboundQueueCaller) ParachainClient(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "parachainClient") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ParachainClient is a free data retrieval call binding the contract method 0x1674f9b7. -// -// Solidity: function parachainClient() view returns(address) -func (_InboundQueue *InboundQueueSession) ParachainClient() (common.Address, error) { - return _InboundQueue.Contract.ParachainClient(&_InboundQueue.CallOpts) -} - -// ParachainClient is a free data retrieval call binding the contract method 0x1674f9b7. -// -// Solidity: function parachainClient() view returns(address) -func (_InboundQueue *InboundQueueCallerSession) ParachainClient() (common.Address, error) { - return _InboundQueue.Contract.ParachainClient(&_InboundQueue.CallOpts) -} - -// Registry is a free data retrieval call binding the contract method 0x7b103999. -// -// Solidity: function registry() view returns(address) -func (_InboundQueue *InboundQueueCaller) Registry(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "registry") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Registry is a free data retrieval call binding the contract method 0x7b103999. -// -// Solidity: function registry() view returns(address) -func (_InboundQueue *InboundQueueSession) Registry() (common.Address, error) { - return _InboundQueue.Contract.Registry(&_InboundQueue.CallOpts) -} - -// Registry is a free data retrieval call binding the contract method 0x7b103999. -// -// Solidity: function registry() view returns(address) -func (_InboundQueue *InboundQueueCallerSession) Registry() (common.Address, error) { - return _InboundQueue.Contract.Registry(&_InboundQueue.CallOpts) -} - -// Reward is a free data retrieval call binding the contract method 0x228cb733. -// -// Solidity: function reward() view returns(uint256) -func (_InboundQueue *InboundQueueCaller) Reward(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "reward") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Reward is a free data retrieval call binding the contract method 0x228cb733. -// -// Solidity: function reward() view returns(uint256) -func (_InboundQueue *InboundQueueSession) Reward() (*big.Int, error) { - return _InboundQueue.Contract.Reward(&_InboundQueue.CallOpts) -} - -// Reward is a free data retrieval call binding the contract method 0x228cb733. -// -// Solidity: function reward() view returns(uint256) -func (_InboundQueue *InboundQueueCallerSession) Reward() (*big.Int, error) { - return _InboundQueue.Contract.Reward(&_InboundQueue.CallOpts) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_InboundQueue *InboundQueueCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_InboundQueue *InboundQueueSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _InboundQueue.Contract.SupportsInterface(&_InboundQueue.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_InboundQueue *InboundQueueCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _InboundQueue.Contract.SupportsInterface(&_InboundQueue.CallOpts, interfaceId) -} - -// Vault is a free data retrieval call binding the contract method 0xfbfa77cf. -// -// Solidity: function vault() view returns(address) -func (_InboundQueue *InboundQueueCaller) Vault(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _InboundQueue.contract.Call(opts, &out, "vault") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Vault is a free data retrieval call binding the contract method 0xfbfa77cf. -// -// Solidity: function vault() view returns(address) -func (_InboundQueue *InboundQueueSession) Vault() (common.Address, error) { - return _InboundQueue.Contract.Vault(&_InboundQueue.CallOpts) -} - -// Vault is a free data retrieval call binding the contract method 0xfbfa77cf. -// -// Solidity: function vault() view returns(address) -func (_InboundQueue *InboundQueueCallerSession) Vault() (common.Address, error) { - return _InboundQueue.Contract.Vault(&_InboundQueue.CallOpts) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.contract.Transact(opts, "grantRole", role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.Contract.GrantRole(&_InboundQueue.TransactOpts, role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.Contract.GrantRole(&_InboundQueue.TransactOpts, role, account) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.contract.Transact(opts, "renounceRole", role, account) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.Contract.RenounceRole(&_InboundQueue.TransactOpts, role, account) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueTransactorSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.Contract.RenounceRole(&_InboundQueue.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.contract.Transact(opts, "revokeRole", role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.Contract.RevokeRole(&_InboundQueue.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_InboundQueue *InboundQueueTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _InboundQueue.Contract.RevokeRole(&_InboundQueue.TransactOpts, role, account) -} - -// Submit is a paid mutator transaction binding the contract method 0x90d7fbe9. -// -// Solidity: function submit((uint32,uint64,bytes32,bytes) message, bytes32[] leafProof, bytes headerProof) returns() -func (_InboundQueue *InboundQueueTransactor) Submit(opts *bind.TransactOpts, message InboundQueueMessage, leafProof [][32]byte, headerProof []byte) (*types.Transaction, error) { - return _InboundQueue.contract.Transact(opts, "submit", message, leafProof, headerProof) -} - -// Submit is a paid mutator transaction binding the contract method 0x90d7fbe9. -// -// Solidity: function submit((uint32,uint64,bytes32,bytes) message, bytes32[] leafProof, bytes headerProof) returns() -func (_InboundQueue *InboundQueueSession) Submit(message InboundQueueMessage, leafProof [][32]byte, headerProof []byte) (*types.Transaction, error) { - return _InboundQueue.Contract.Submit(&_InboundQueue.TransactOpts, message, leafProof, headerProof) -} - -// Submit is a paid mutator transaction binding the contract method 0x90d7fbe9. -// -// Solidity: function submit((uint32,uint64,bytes32,bytes) message, bytes32[] leafProof, bytes headerProof) returns() -func (_InboundQueue *InboundQueueTransactorSession) Submit(message InboundQueueMessage, leafProof [][32]byte, headerProof []byte) (*types.Transaction, error) { - return _InboundQueue.Contract.Submit(&_InboundQueue.TransactOpts, message, leafProof, headerProof) -} - -// UpdateGasToForward is a paid mutator transaction binding the contract method 0xf4d9d4c4. -// -// Solidity: function updateGasToForward(uint256 _gasToForward) returns() -func (_InboundQueue *InboundQueueTransactor) UpdateGasToForward(opts *bind.TransactOpts, _gasToForward *big.Int) (*types.Transaction, error) { - return _InboundQueue.contract.Transact(opts, "updateGasToForward", _gasToForward) -} - -// UpdateGasToForward is a paid mutator transaction binding the contract method 0xf4d9d4c4. -// -// Solidity: function updateGasToForward(uint256 _gasToForward) returns() -func (_InboundQueue *InboundQueueSession) UpdateGasToForward(_gasToForward *big.Int) (*types.Transaction, error) { - return _InboundQueue.Contract.UpdateGasToForward(&_InboundQueue.TransactOpts, _gasToForward) -} - -// UpdateGasToForward is a paid mutator transaction binding the contract method 0xf4d9d4c4. -// -// Solidity: function updateGasToForward(uint256 _gasToForward) returns() -func (_InboundQueue *InboundQueueTransactorSession) UpdateGasToForward(_gasToForward *big.Int) (*types.Transaction, error) { - return _InboundQueue.Contract.UpdateGasToForward(&_InboundQueue.TransactOpts, _gasToForward) -} - -// UpdateReward is a paid mutator transaction binding the contract method 0x425c8abd. -// -// Solidity: function updateReward(uint256 _reward) returns() -func (_InboundQueue *InboundQueueTransactor) UpdateReward(opts *bind.TransactOpts, _reward *big.Int) (*types.Transaction, error) { - return _InboundQueue.contract.Transact(opts, "updateReward", _reward) -} - -// UpdateReward is a paid mutator transaction binding the contract method 0x425c8abd. -// -// Solidity: function updateReward(uint256 _reward) returns() -func (_InboundQueue *InboundQueueSession) UpdateReward(_reward *big.Int) (*types.Transaction, error) { - return _InboundQueue.Contract.UpdateReward(&_InboundQueue.TransactOpts, _reward) -} - -// UpdateReward is a paid mutator transaction binding the contract method 0x425c8abd. -// -// Solidity: function updateReward(uint256 _reward) returns() -func (_InboundQueue *InboundQueueTransactorSession) UpdateReward(_reward *big.Int) (*types.Transaction, error) { - return _InboundQueue.Contract.UpdateReward(&_InboundQueue.TransactOpts, _reward) -} - -// InboundQueueGasToForwardUpdatedIterator is returned from FilterGasToForwardUpdated and is used to iterate over the raw logs and unpacked data for GasToForwardUpdated events raised by the InboundQueue contract. -type InboundQueueGasToForwardUpdatedIterator struct { - Event *InboundQueueGasToForwardUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueGasToForwardUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueGasToForwardUpdated) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueGasToForwardUpdated) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueGasToForwardUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueGasToForwardUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueGasToForwardUpdated represents a GasToForwardUpdated event raised by the InboundQueue contract. -type InboundQueueGasToForwardUpdated struct { - GasToForward *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterGasToForwardUpdated is a free log retrieval operation binding the contract event 0x100f863b8d0f17ca3e98e1ee23dc6feb2a31f24f0836e89e21bcb9f0bfc2d742. -// -// Solidity: event GasToForwardUpdated(uint256 gasToForward) -func (_InboundQueue *InboundQueueFilterer) FilterGasToForwardUpdated(opts *bind.FilterOpts) (*InboundQueueGasToForwardUpdatedIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "GasToForwardUpdated") - if err != nil { - return nil, err - } - return &InboundQueueGasToForwardUpdatedIterator{contract: _InboundQueue.contract, event: "GasToForwardUpdated", logs: logs, sub: sub}, nil -} - -// WatchGasToForwardUpdated is a free log subscription operation binding the contract event 0x100f863b8d0f17ca3e98e1ee23dc6feb2a31f24f0836e89e21bcb9f0bfc2d742. -// -// Solidity: event GasToForwardUpdated(uint256 gasToForward) -func (_InboundQueue *InboundQueueFilterer) WatchGasToForwardUpdated(opts *bind.WatchOpts, sink chan<- *InboundQueueGasToForwardUpdated) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "GasToForwardUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueGasToForwardUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "GasToForwardUpdated", 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 -} - -// ParseGasToForwardUpdated is a log parse operation binding the contract event 0x100f863b8d0f17ca3e98e1ee23dc6feb2a31f24f0836e89e21bcb9f0bfc2d742. -// -// Solidity: event GasToForwardUpdated(uint256 gasToForward) -func (_InboundQueue *InboundQueueFilterer) ParseGasToForwardUpdated(log types.Log) (*InboundQueueGasToForwardUpdated, error) { - event := new(InboundQueueGasToForwardUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "GasToForwardUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueHandlerUpdatedIterator is returned from FilterHandlerUpdated and is used to iterate over the raw logs and unpacked data for HandlerUpdated events raised by the InboundQueue contract. -type InboundQueueHandlerUpdatedIterator struct { - Event *InboundQueueHandlerUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueHandlerUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueHandlerUpdated) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueHandlerUpdated) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueHandlerUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueHandlerUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueHandlerUpdated represents a HandlerUpdated event raised by the InboundQueue contract. -type InboundQueueHandlerUpdated struct { - Id uint16 - Handler common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterHandlerUpdated is a free log retrieval operation binding the contract event 0x3ed918ab4515fda74eadc324a45e89778c4e8bfc6391f78db7beac41b768df74. -// -// Solidity: event HandlerUpdated(uint16 id, address handler) -func (_InboundQueue *InboundQueueFilterer) FilterHandlerUpdated(opts *bind.FilterOpts) (*InboundQueueHandlerUpdatedIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "HandlerUpdated") - if err != nil { - return nil, err - } - return &InboundQueueHandlerUpdatedIterator{contract: _InboundQueue.contract, event: "HandlerUpdated", logs: logs, sub: sub}, nil -} - -// WatchHandlerUpdated is a free log subscription operation binding the contract event 0x3ed918ab4515fda74eadc324a45e89778c4e8bfc6391f78db7beac41b768df74. -// -// Solidity: event HandlerUpdated(uint16 id, address handler) -func (_InboundQueue *InboundQueueFilterer) WatchHandlerUpdated(opts *bind.WatchOpts, sink chan<- *InboundQueueHandlerUpdated) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "HandlerUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueHandlerUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "HandlerUpdated", 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 -} - -// ParseHandlerUpdated is a log parse operation binding the contract event 0x3ed918ab4515fda74eadc324a45e89778c4e8bfc6391f78db7beac41b768df74. -// -// Solidity: event HandlerUpdated(uint16 id, address handler) -func (_InboundQueue *InboundQueueFilterer) ParseHandlerUpdated(log types.Log) (*InboundQueueHandlerUpdated, error) { - event := new(InboundQueueHandlerUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "HandlerUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueInvalidRecipientIterator is returned from FilterInvalidRecipient and is used to iterate over the raw logs and unpacked data for InvalidRecipient events raised by the InboundQueue contract. -type InboundQueueInvalidRecipientIterator struct { - Event *InboundQueueInvalidRecipient // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueInvalidRecipientIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueInvalidRecipient) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueInvalidRecipient) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueInvalidRecipientIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueInvalidRecipientIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueInvalidRecipient represents a InvalidRecipient event raised by the InboundQueue contract. -type InboundQueueInvalidRecipient struct { - Recipient [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInvalidRecipient is a free log retrieval operation binding the contract event 0xbf0b3f6242271405146290163e141ff674b9d85a2a16815a195bb05e3d57c835. -// -// Solidity: event InvalidRecipient(bytes32 recipient) -func (_InboundQueue *InboundQueueFilterer) FilterInvalidRecipient(opts *bind.FilterOpts) (*InboundQueueInvalidRecipientIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "InvalidRecipient") - if err != nil { - return nil, err - } - return &InboundQueueInvalidRecipientIterator{contract: _InboundQueue.contract, event: "InvalidRecipient", logs: logs, sub: sub}, nil -} - -// WatchInvalidRecipient is a free log subscription operation binding the contract event 0xbf0b3f6242271405146290163e141ff674b9d85a2a16815a195bb05e3d57c835. -// -// Solidity: event InvalidRecipient(bytes32 recipient) -func (_InboundQueue *InboundQueueFilterer) WatchInvalidRecipient(opts *bind.WatchOpts, sink chan<- *InboundQueueInvalidRecipient) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "InvalidRecipient") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueInvalidRecipient) - if err := _InboundQueue.contract.UnpackLog(event, "InvalidRecipient", 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 -} - -// ParseInvalidRecipient is a log parse operation binding the contract event 0xbf0b3f6242271405146290163e141ff674b9d85a2a16815a195bb05e3d57c835. -// -// Solidity: event InvalidRecipient(bytes32 recipient) -func (_InboundQueue *InboundQueueFilterer) ParseInvalidRecipient(log types.Log) (*InboundQueueInvalidRecipient, error) { - event := new(InboundQueueInvalidRecipient) - if err := _InboundQueue.contract.UnpackLog(event, "InvalidRecipient", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueMessageDispatchedIterator is returned from FilterMessageDispatched and is used to iterate over the raw logs and unpacked data for MessageDispatched events raised by the InboundQueue contract. -type InboundQueueMessageDispatchedIterator struct { - Event *InboundQueueMessageDispatched // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueMessageDispatchedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueMessageDispatched) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueMessageDispatched) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueMessageDispatchedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueMessageDispatchedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueMessageDispatched represents a MessageDispatched event raised by the InboundQueue contract. -type InboundQueueMessageDispatched struct { - Origin uint32 - Nonce uint64 - Result uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterMessageDispatched is a free log retrieval operation binding the contract event 0x3daaaf6b5c13966eb060b53daff310d82d35bdd2e539be4dc92dfe1310ee170d. -// -// Solidity: event MessageDispatched(uint32 origin, uint64 nonce, uint8 result) -func (_InboundQueue *InboundQueueFilterer) FilterMessageDispatched(opts *bind.FilterOpts) (*InboundQueueMessageDispatchedIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "MessageDispatched") - if err != nil { - return nil, err - } - return &InboundQueueMessageDispatchedIterator{contract: _InboundQueue.contract, event: "MessageDispatched", logs: logs, sub: sub}, nil -} - -// WatchMessageDispatched is a free log subscription operation binding the contract event 0x3daaaf6b5c13966eb060b53daff310d82d35bdd2e539be4dc92dfe1310ee170d. -// -// Solidity: event MessageDispatched(uint32 origin, uint64 nonce, uint8 result) -func (_InboundQueue *InboundQueueFilterer) WatchMessageDispatched(opts *bind.WatchOpts, sink chan<- *InboundQueueMessageDispatched) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "MessageDispatched") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueMessageDispatched) - if err := _InboundQueue.contract.UnpackLog(event, "MessageDispatched", 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 -} - -// ParseMessageDispatched is a log parse operation binding the contract event 0x3daaaf6b5c13966eb060b53daff310d82d35bdd2e539be4dc92dfe1310ee170d. -// -// Solidity: event MessageDispatched(uint32 origin, uint64 nonce, uint8 result) -func (_InboundQueue *InboundQueueFilterer) ParseMessageDispatched(log types.Log) (*InboundQueueMessageDispatched, error) { - event := new(InboundQueueMessageDispatched) - if err := _InboundQueue.contract.UnpackLog(event, "MessageDispatched", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueParachainClientUpdatedIterator is returned from FilterParachainClientUpdated and is used to iterate over the raw logs and unpacked data for ParachainClientUpdated events raised by the InboundQueue contract. -type InboundQueueParachainClientUpdatedIterator struct { - Event *InboundQueueParachainClientUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueParachainClientUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueParachainClientUpdated) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueParachainClientUpdated) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueParachainClientUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueParachainClientUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueParachainClientUpdated represents a ParachainClientUpdated event raised by the InboundQueue contract. -type InboundQueueParachainClientUpdated struct { - ParachainClient common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterParachainClientUpdated is a free log retrieval operation binding the contract event 0x2eb3efb9388b586c251856bc1b31af67a4015796cf665e600df15d2a42e2ba41. -// -// Solidity: event ParachainClientUpdated(address parachainClient) -func (_InboundQueue *InboundQueueFilterer) FilterParachainClientUpdated(opts *bind.FilterOpts) (*InboundQueueParachainClientUpdatedIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "ParachainClientUpdated") - if err != nil { - return nil, err - } - return &InboundQueueParachainClientUpdatedIterator{contract: _InboundQueue.contract, event: "ParachainClientUpdated", logs: logs, sub: sub}, nil -} - -// WatchParachainClientUpdated is a free log subscription operation binding the contract event 0x2eb3efb9388b586c251856bc1b31af67a4015796cf665e600df15d2a42e2ba41. -// -// Solidity: event ParachainClientUpdated(address parachainClient) -func (_InboundQueue *InboundQueueFilterer) WatchParachainClientUpdated(opts *bind.WatchOpts, sink chan<- *InboundQueueParachainClientUpdated) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "ParachainClientUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueParachainClientUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "ParachainClientUpdated", 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 -} - -// ParseParachainClientUpdated is a log parse operation binding the contract event 0x2eb3efb9388b586c251856bc1b31af67a4015796cf665e600df15d2a42e2ba41. -// -// Solidity: event ParachainClientUpdated(address parachainClient) -func (_InboundQueue *InboundQueueFilterer) ParseParachainClientUpdated(log types.Log) (*InboundQueueParachainClientUpdated, error) { - event := new(InboundQueueParachainClientUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "ParachainClientUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueRewardUpdatedIterator is returned from FilterRewardUpdated and is used to iterate over the raw logs and unpacked data for RewardUpdated events raised by the InboundQueue contract. -type InboundQueueRewardUpdatedIterator struct { - Event *InboundQueueRewardUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueRewardUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueRewardUpdated) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueRewardUpdated) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueRewardUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueRewardUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueRewardUpdated represents a RewardUpdated event raised by the InboundQueue contract. -type InboundQueueRewardUpdated struct { - Reward *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRewardUpdated is a free log retrieval operation binding the contract event 0xcb94909754d27c309adf4167150f1f7aa04de40b6a0e6bb98b2ae80a2bf438f6. -// -// Solidity: event RewardUpdated(uint256 reward) -func (_InboundQueue *InboundQueueFilterer) FilterRewardUpdated(opts *bind.FilterOpts) (*InboundQueueRewardUpdatedIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "RewardUpdated") - if err != nil { - return nil, err - } - return &InboundQueueRewardUpdatedIterator{contract: _InboundQueue.contract, event: "RewardUpdated", logs: logs, sub: sub}, nil -} - -// WatchRewardUpdated is a free log subscription operation binding the contract event 0xcb94909754d27c309adf4167150f1f7aa04de40b6a0e6bb98b2ae80a2bf438f6. -// -// Solidity: event RewardUpdated(uint256 reward) -func (_InboundQueue *InboundQueueFilterer) WatchRewardUpdated(opts *bind.WatchOpts, sink chan<- *InboundQueueRewardUpdated) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "RewardUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueRewardUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "RewardUpdated", 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 -} - -// ParseRewardUpdated is a log parse operation binding the contract event 0xcb94909754d27c309adf4167150f1f7aa04de40b6a0e6bb98b2ae80a2bf438f6. -// -// Solidity: event RewardUpdated(uint256 reward) -func (_InboundQueue *InboundQueueFilterer) ParseRewardUpdated(log types.Log) (*InboundQueueRewardUpdated, error) { - event := new(InboundQueueRewardUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "RewardUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the InboundQueue contract. -type InboundQueueRoleAdminChangedIterator struct { - Event *InboundQueueRoleAdminChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueRoleAdminChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueRoleAdminChanged) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueRoleAdminChanged) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueRoleAdminChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueRoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueRoleAdminChanged represents a RoleAdminChanged event raised by the InboundQueue contract. -type InboundQueueRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_InboundQueue *InboundQueueFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*InboundQueueRoleAdminChangedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return &InboundQueueRoleAdminChangedIterator{contract: _InboundQueue.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil -} - -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_InboundQueue *InboundQueueFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *InboundQueueRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueRoleAdminChanged) - if err := _InboundQueue.contract.UnpackLog(event, "RoleAdminChanged", 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 -} - -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_InboundQueue *InboundQueueFilterer) ParseRoleAdminChanged(log types.Log) (*InboundQueueRoleAdminChanged, error) { - event := new(InboundQueueRoleAdminChanged) - if err := _InboundQueue.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the InboundQueue contract. -type InboundQueueRoleGrantedIterator struct { - Event *InboundQueueRoleGranted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueRoleGrantedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueRoleGranted) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueRoleGranted) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueRoleGrantedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueRoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueRoleGranted represents a RoleGranted event raised by the InboundQueue contract. -type InboundQueueRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_InboundQueue *InboundQueueFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*InboundQueueRoleGrantedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &InboundQueueRoleGrantedIterator{contract: _InboundQueue.contract, event: "RoleGranted", logs: logs, sub: sub}, nil -} - -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_InboundQueue *InboundQueueFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *InboundQueueRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueRoleGranted) - if err := _InboundQueue.contract.UnpackLog(event, "RoleGranted", 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 -} - -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_InboundQueue *InboundQueueFilterer) ParseRoleGranted(log types.Log) (*InboundQueueRoleGranted, error) { - event := new(InboundQueueRoleGranted) - if err := _InboundQueue.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the InboundQueue contract. -type InboundQueueRoleRevokedIterator struct { - Event *InboundQueueRoleRevoked // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueRoleRevokedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueRoleRevoked) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueRoleRevoked) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueRoleRevokedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueRoleRevokedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueRoleRevoked represents a RoleRevoked event raised by the InboundQueue contract. -type InboundQueueRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_InboundQueue *InboundQueueFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*InboundQueueRoleRevokedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &InboundQueueRoleRevokedIterator{contract: _InboundQueue.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil -} - -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_InboundQueue *InboundQueueFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *InboundQueueRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueRoleRevoked) - if err := _InboundQueue.contract.UnpackLog(event, "RoleRevoked", 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 -} - -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_InboundQueue *InboundQueueFilterer) ParseRoleRevoked(log types.Log) (*InboundQueueRoleRevoked, error) { - event := new(InboundQueueRoleRevoked) - if err := _InboundQueue.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InboundQueueVaultUpdatedIterator is returned from FilterVaultUpdated and is used to iterate over the raw logs and unpacked data for VaultUpdated events raised by the InboundQueue contract. -type InboundQueueVaultUpdatedIterator struct { - Event *InboundQueueVaultUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InboundQueueVaultUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InboundQueueVaultUpdated) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InboundQueueVaultUpdated) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InboundQueueVaultUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InboundQueueVaultUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InboundQueueVaultUpdated represents a VaultUpdated event raised by the InboundQueue contract. -type InboundQueueVaultUpdated struct { - Vault common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterVaultUpdated is a free log retrieval operation binding the contract event 0x161584aed96e7f34998117c9ad67e2d21ff46d2a42775c22b11ed282f3c7b2cd. -// -// Solidity: event VaultUpdated(address vault) -func (_InboundQueue *InboundQueueFilterer) FilterVaultUpdated(opts *bind.FilterOpts) (*InboundQueueVaultUpdatedIterator, error) { - - logs, sub, err := _InboundQueue.contract.FilterLogs(opts, "VaultUpdated") - if err != nil { - return nil, err - } - return &InboundQueueVaultUpdatedIterator{contract: _InboundQueue.contract, event: "VaultUpdated", logs: logs, sub: sub}, nil -} - -// WatchVaultUpdated is a free log subscription operation binding the contract event 0x161584aed96e7f34998117c9ad67e2d21ff46d2a42775c22b11ed282f3c7b2cd. -// -// Solidity: event VaultUpdated(address vault) -func (_InboundQueue *InboundQueueFilterer) WatchVaultUpdated(opts *bind.WatchOpts, sink chan<- *InboundQueueVaultUpdated) (event.Subscription, error) { - - logs, sub, err := _InboundQueue.contract.WatchLogs(opts, "VaultUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InboundQueueVaultUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "VaultUpdated", 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 -} - -// ParseVaultUpdated is a log parse operation binding the contract event 0x161584aed96e7f34998117c9ad67e2d21ff46d2a42775c22b11ed282f3c7b2cd. -// -// Solidity: event VaultUpdated(address vault) -func (_InboundQueue *InboundQueueFilterer) ParseVaultUpdated(log types.Log) (*InboundQueueVaultUpdated, error) { - event := new(InboundQueueVaultUpdated) - if err := _InboundQueue.contract.UnpackLog(event, "VaultUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/contracts/opaque_proof.go b/relayer/contracts/opaque_proof.go deleted file mode 100644 index f118dbd2c721a..0000000000000 --- a/relayer/contracts/opaque_proof.go +++ /dev/null @@ -1,251 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contracts - -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" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// ParachainClientDigestItem is an auto generated low-level Go binding around an user-defined struct. -type ParachainClientDigestItem struct { - Kind *big.Int - ConsensusEngineID [4]byte - Data []byte -} - -// ParachainClientHeadProof is an auto generated low-level Go binding around an user-defined struct. -type ParachainClientHeadProof struct { - Pos *big.Int - Width *big.Int - Proof [][32]byte -} - -// ParachainClientMMRLeafPartial is an auto generated low-level Go binding around an user-defined struct. -type ParachainClientMMRLeafPartial struct { - Version uint8 - ParentNumber uint32 - ParentHash [32]byte - NextAuthoritySetID uint64 - NextAuthoritySetLen uint32 - NextAuthoritySetRoot [32]byte -} - -// ParachainClientParachainHeader is an auto generated low-level Go binding around an user-defined struct. -type ParachainClientParachainHeader struct { - ParentHash [32]byte - Number *big.Int - StateRoot [32]byte - ExtrinsicsRoot [32]byte - DigestItems []ParachainClientDigestItem -} - -// ParachainClientProof is an auto generated low-level Go binding around an user-defined struct. -type ParachainClientProof struct { - Header ParachainClientParachainHeader - HeadProof ParachainClientHeadProof - LeafPartial ParachainClientMMRLeafPartial - LeafProof [][32]byte - LeafProofOrder *big.Int -} - -// OpaqueProofMetaData contains all meta data concerning the OpaqueProof contract. -var OpaqueProofMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"parentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"extrinsicsRoot\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"kind\",\"type\":\"uint256\"},{\"internalType\":\"bytes4\",\"name\":\"consensusEngineID\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structParachainClient.DigestItem[]\",\"name\":\"digestItems\",\"type\":\"tuple[]\"}],\"internalType\":\"structParachainClient.ParachainHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"pos\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"width\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"internalType\":\"structParachainClient.HeadProof\",\"name\":\"headProof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"parentNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"parentHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structParachainClient.MMRLeafPartial\",\"name\":\"leafPartial\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"leafProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"leafProofOrder\",\"type\":\"uint256\"}],\"internalType\":\"structParachainClient.Proof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"dummy\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}]", -} - -// OpaqueProofABI is the input ABI used to generate the binding from. -// Deprecated: Use OpaqueProofMetaData.ABI instead. -var OpaqueProofABI = OpaqueProofMetaData.ABI - -// OpaqueProof is an auto generated Go binding around an Ethereum contract. -type OpaqueProof struct { - OpaqueProofCaller // Read-only binding to the contract - OpaqueProofTransactor // Write-only binding to the contract - OpaqueProofFilterer // Log filterer for contract events -} - -// OpaqueProofCaller is an auto generated read-only Go binding around an Ethereum contract. -type OpaqueProofCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OpaqueProofTransactor is an auto generated write-only Go binding around an Ethereum contract. -type OpaqueProofTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OpaqueProofFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type OpaqueProofFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OpaqueProofSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type OpaqueProofSession struct { - Contract *OpaqueProof // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OpaqueProofCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type OpaqueProofCallerSession struct { - Contract *OpaqueProofCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// OpaqueProofTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type OpaqueProofTransactorSession struct { - Contract *OpaqueProofTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OpaqueProofRaw is an auto generated low-level Go binding around an Ethereum contract. -type OpaqueProofRaw struct { - Contract *OpaqueProof // Generic contract binding to access the raw methods on -} - -// OpaqueProofCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type OpaqueProofCallerRaw struct { - Contract *OpaqueProofCaller // Generic read-only contract binding to access the raw methods on -} - -// OpaqueProofTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type OpaqueProofTransactorRaw struct { - Contract *OpaqueProofTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewOpaqueProof creates a new instance of OpaqueProof, bound to a specific deployed contract. -func NewOpaqueProof(address common.Address, backend bind.ContractBackend) (*OpaqueProof, error) { - contract, err := bindOpaqueProof(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &OpaqueProof{OpaqueProofCaller: OpaqueProofCaller{contract: contract}, OpaqueProofTransactor: OpaqueProofTransactor{contract: contract}, OpaqueProofFilterer: OpaqueProofFilterer{contract: contract}}, nil -} - -// NewOpaqueProofCaller creates a new read-only instance of OpaqueProof, bound to a specific deployed contract. -func NewOpaqueProofCaller(address common.Address, caller bind.ContractCaller) (*OpaqueProofCaller, error) { - contract, err := bindOpaqueProof(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &OpaqueProofCaller{contract: contract}, nil -} - -// NewOpaqueProofTransactor creates a new write-only instance of OpaqueProof, bound to a specific deployed contract. -func NewOpaqueProofTransactor(address common.Address, transactor bind.ContractTransactor) (*OpaqueProofTransactor, error) { - contract, err := bindOpaqueProof(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &OpaqueProofTransactor{contract: contract}, nil -} - -// NewOpaqueProofFilterer creates a new log filterer instance of OpaqueProof, bound to a specific deployed contract. -func NewOpaqueProofFilterer(address common.Address, filterer bind.ContractFilterer) (*OpaqueProofFilterer, error) { - contract, err := bindOpaqueProof(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &OpaqueProofFilterer{contract: contract}, nil -} - -// bindOpaqueProof binds a generic wrapper to an already deployed contract. -func bindOpaqueProof(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(OpaqueProofABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_OpaqueProof *OpaqueProofRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OpaqueProof.Contract.OpaqueProofCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_OpaqueProof *OpaqueProofRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OpaqueProof.Contract.OpaqueProofTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_OpaqueProof *OpaqueProofRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OpaqueProof.Contract.OpaqueProofTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_OpaqueProof *OpaqueProofCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OpaqueProof.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_OpaqueProof *OpaqueProofTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OpaqueProof.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_OpaqueProof *OpaqueProofTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OpaqueProof.Contract.contract.Transact(opts, method, params...) -} - -// Dummy is a free data retrieval call binding the contract method 0xa454dc91. -// -// Solidity: function dummy(((bytes32,uint256,bytes32,bytes32,(uint256,bytes4,bytes)[]),(uint256,uint256,bytes32[]),(uint8,uint32,bytes32,uint64,uint32,bytes32),bytes32[],uint256) proof) pure returns() -func (_OpaqueProof *OpaqueProofCaller) Dummy(opts *bind.CallOpts, proof ParachainClientProof) error { - var out []interface{} - err := _OpaqueProof.contract.Call(opts, &out, "dummy", proof) - - if err != nil { - return err - } - - return err - -} - -// Dummy is a free data retrieval call binding the contract method 0xa454dc91. -// -// Solidity: function dummy(((bytes32,uint256,bytes32,bytes32,(uint256,bytes4,bytes)[]),(uint256,uint256,bytes32[]),(uint8,uint32,bytes32,uint64,uint32,bytes32),bytes32[],uint256) proof) pure returns() -func (_OpaqueProof *OpaqueProofSession) Dummy(proof ParachainClientProof) error { - return _OpaqueProof.Contract.Dummy(&_OpaqueProof.CallOpts, proof) -} - -// Dummy is a free data retrieval call binding the contract method 0xa454dc91. -// -// Solidity: function dummy(((bytes32,uint256,bytes32,bytes32,(uint256,bytes4,bytes)[]),(uint256,uint256,bytes32[]),(uint8,uint32,bytes32,uint64,uint32,bytes32),bytes32[],uint256) proof) pure returns() -func (_OpaqueProof *OpaqueProofCallerSession) Dummy(proof ParachainClientProof) error { - return _OpaqueProof.Contract.Dummy(&_OpaqueProof.CallOpts, proof) -} diff --git a/relayer/contracts/outbound_queue.go b/relayer/contracts/outbound_queue.go deleted file mode 100644 index d8898b12cebaf..0000000000000 --- a/relayer/contracts/outbound_queue.go +++ /dev/null @@ -1,1369 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contracts - -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" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription -) - -// OutboundQueueMetaData contains all meta data concerning the OutboundQueue contract. -var OutboundQueueMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractVault\",\"name\":\"_vault\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FeePaymentToLow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LookupError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"name\":\"FeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"ParaID\",\"name\":\"dest\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"Message\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"SUBMIT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ParaID\",\"name\":\"dest\",\"type\":\"uint32\"}],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"contractRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"ParaID\",\"name\":\"dest\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"submit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFee\",\"type\":\"uint256\"}],\"name\":\"updateFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vault\",\"outputs\":[{\"internalType\":\"contractVault\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", -} - -// OutboundQueueABI is the input ABI used to generate the binding from. -// Deprecated: Use OutboundQueueMetaData.ABI instead. -var OutboundQueueABI = OutboundQueueMetaData.ABI - -// OutboundQueue is an auto generated Go binding around an Ethereum contract. -type OutboundQueue struct { - OutboundQueueCaller // Read-only binding to the contract - OutboundQueueTransactor // Write-only binding to the contract - OutboundQueueFilterer // Log filterer for contract events -} - -// OutboundQueueCaller is an auto generated read-only Go binding around an Ethereum contract. -type OutboundQueueCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OutboundQueueTransactor is an auto generated write-only Go binding around an Ethereum contract. -type OutboundQueueTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OutboundQueueFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type OutboundQueueFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// OutboundQueueSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type OutboundQueueSession struct { - Contract *OutboundQueue // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OutboundQueueCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type OutboundQueueCallerSession struct { - Contract *OutboundQueueCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// OutboundQueueTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type OutboundQueueTransactorSession struct { - Contract *OutboundQueueTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// OutboundQueueRaw is an auto generated low-level Go binding around an Ethereum contract. -type OutboundQueueRaw struct { - Contract *OutboundQueue // Generic contract binding to access the raw methods on -} - -// OutboundQueueCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type OutboundQueueCallerRaw struct { - Contract *OutboundQueueCaller // Generic read-only contract binding to access the raw methods on -} - -// OutboundQueueTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type OutboundQueueTransactorRaw struct { - Contract *OutboundQueueTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewOutboundQueue creates a new instance of OutboundQueue, bound to a specific deployed contract. -func NewOutboundQueue(address common.Address, backend bind.ContractBackend) (*OutboundQueue, error) { - contract, err := bindOutboundQueue(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &OutboundQueue{OutboundQueueCaller: OutboundQueueCaller{contract: contract}, OutboundQueueTransactor: OutboundQueueTransactor{contract: contract}, OutboundQueueFilterer: OutboundQueueFilterer{contract: contract}}, nil -} - -// NewOutboundQueueCaller creates a new read-only instance of OutboundQueue, bound to a specific deployed contract. -func NewOutboundQueueCaller(address common.Address, caller bind.ContractCaller) (*OutboundQueueCaller, error) { - contract, err := bindOutboundQueue(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &OutboundQueueCaller{contract: contract}, nil -} - -// NewOutboundQueueTransactor creates a new write-only instance of OutboundQueue, bound to a specific deployed contract. -func NewOutboundQueueTransactor(address common.Address, transactor bind.ContractTransactor) (*OutboundQueueTransactor, error) { - contract, err := bindOutboundQueue(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &OutboundQueueTransactor{contract: contract}, nil -} - -// NewOutboundQueueFilterer creates a new log filterer instance of OutboundQueue, bound to a specific deployed contract. -func NewOutboundQueueFilterer(address common.Address, filterer bind.ContractFilterer) (*OutboundQueueFilterer, error) { - contract, err := bindOutboundQueue(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &OutboundQueueFilterer{contract: contract}, nil -} - -// bindOutboundQueue binds a generic wrapper to an already deployed contract. -func bindOutboundQueue(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(OutboundQueueABI)) - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_OutboundQueue *OutboundQueueRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OutboundQueue.Contract.OutboundQueueCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_OutboundQueue *OutboundQueueRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OutboundQueue.Contract.OutboundQueueTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_OutboundQueue *OutboundQueueRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OutboundQueue.Contract.OutboundQueueTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_OutboundQueue *OutboundQueueCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OutboundQueue.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_OutboundQueue *OutboundQueueTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OutboundQueue.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_OutboundQueue *OutboundQueueTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OutboundQueue.Contract.contract.Transact(opts, method, params...) -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueCaller) ADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueSession) ADMINROLE() ([32]byte, error) { - return _OutboundQueue.Contract.ADMINROLE(&_OutboundQueue.CallOpts) -} - -// ADMINROLE is a free data retrieval call binding the contract method 0x75b238fc. -// -// Solidity: function ADMIN_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueCallerSession) ADMINROLE() ([32]byte, error) { - return _OutboundQueue.Contract.ADMINROLE(&_OutboundQueue.CallOpts) -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueSession) DEFAULTADMINROLE() ([32]byte, error) { - return _OutboundQueue.Contract.DEFAULTADMINROLE(&_OutboundQueue.CallOpts) -} - -// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. -// -// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueCallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _OutboundQueue.Contract.DEFAULTADMINROLE(&_OutboundQueue.CallOpts) -} - -// SUBMITROLE is a free data retrieval call binding the contract method 0xa9c0c694. -// -// Solidity: function SUBMIT_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueCaller) SUBMITROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "SUBMIT_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// SUBMITROLE is a free data retrieval call binding the contract method 0xa9c0c694. -// -// Solidity: function SUBMIT_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueSession) SUBMITROLE() ([32]byte, error) { - return _OutboundQueue.Contract.SUBMITROLE(&_OutboundQueue.CallOpts) -} - -// SUBMITROLE is a free data retrieval call binding the contract method 0xa9c0c694. -// -// Solidity: function SUBMIT_ROLE() view returns(bytes32) -func (_OutboundQueue *OutboundQueueCallerSession) SUBMITROLE() ([32]byte, error) { - return _OutboundQueue.Contract.SUBMITROLE(&_OutboundQueue.CallOpts) -} - -// Fee is a free data retrieval call binding the contract method 0xddca3f43. -// -// Solidity: function fee() view returns(uint256) -func (_OutboundQueue *OutboundQueueCaller) Fee(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "fee") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Fee is a free data retrieval call binding the contract method 0xddca3f43. -// -// Solidity: function fee() view returns(uint256) -func (_OutboundQueue *OutboundQueueSession) Fee() (*big.Int, error) { - return _OutboundQueue.Contract.Fee(&_OutboundQueue.CallOpts) -} - -// Fee is a free data retrieval call binding the contract method 0xddca3f43. -// -// Solidity: function fee() view returns(uint256) -func (_OutboundQueue *OutboundQueueCallerSession) Fee() (*big.Int, error) { - return _OutboundQueue.Contract.Fee(&_OutboundQueue.CallOpts) -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_OutboundQueue *OutboundQueueCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "getRoleAdmin", role) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_OutboundQueue *OutboundQueueSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _OutboundQueue.Contract.GetRoleAdmin(&_OutboundQueue.CallOpts, role) -} - -// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. -// -// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) -func (_OutboundQueue *OutboundQueueCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _OutboundQueue.Contract.GetRoleAdmin(&_OutboundQueue.CallOpts, role) -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_OutboundQueue *OutboundQueueCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "hasRole", role, account) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_OutboundQueue *OutboundQueueSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _OutboundQueue.Contract.HasRole(&_OutboundQueue.CallOpts, role, account) -} - -// HasRole is a free data retrieval call binding the contract method 0x91d14854. -// -// Solidity: function hasRole(bytes32 role, address account) view returns(bool) -func (_OutboundQueue *OutboundQueueCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _OutboundQueue.Contract.HasRole(&_OutboundQueue.CallOpts, role, account) -} - -// Nonce is a free data retrieval call binding the contract method 0x141c4985. -// -// Solidity: function nonce(uint32 dest) view returns(uint64) -func (_OutboundQueue *OutboundQueueCaller) Nonce(opts *bind.CallOpts, dest uint32) (uint64, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "nonce", dest) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// Nonce is a free data retrieval call binding the contract method 0x141c4985. -// -// Solidity: function nonce(uint32 dest) view returns(uint64) -func (_OutboundQueue *OutboundQueueSession) Nonce(dest uint32) (uint64, error) { - return _OutboundQueue.Contract.Nonce(&_OutboundQueue.CallOpts, dest) -} - -// Nonce is a free data retrieval call binding the contract method 0x141c4985. -// -// Solidity: function nonce(uint32 dest) view returns(uint64) -func (_OutboundQueue *OutboundQueueCallerSession) Nonce(dest uint32) (uint64, error) { - return _OutboundQueue.Contract.Nonce(&_OutboundQueue.CallOpts, dest) -} - -// Registry is a free data retrieval call binding the contract method 0x7b103999. -// -// Solidity: function registry() view returns(address) -func (_OutboundQueue *OutboundQueueCaller) Registry(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "registry") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Registry is a free data retrieval call binding the contract method 0x7b103999. -// -// Solidity: function registry() view returns(address) -func (_OutboundQueue *OutboundQueueSession) Registry() (common.Address, error) { - return _OutboundQueue.Contract.Registry(&_OutboundQueue.CallOpts) -} - -// Registry is a free data retrieval call binding the contract method 0x7b103999. -// -// Solidity: function registry() view returns(address) -func (_OutboundQueue *OutboundQueueCallerSession) Registry() (common.Address, error) { - return _OutboundQueue.Contract.Registry(&_OutboundQueue.CallOpts) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_OutboundQueue *OutboundQueueCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_OutboundQueue *OutboundQueueSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _OutboundQueue.Contract.SupportsInterface(&_OutboundQueue.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_OutboundQueue *OutboundQueueCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _OutboundQueue.Contract.SupportsInterface(&_OutboundQueue.CallOpts, interfaceId) -} - -// Vault is a free data retrieval call binding the contract method 0xfbfa77cf. -// -// Solidity: function vault() view returns(address) -func (_OutboundQueue *OutboundQueueCaller) Vault(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _OutboundQueue.contract.Call(opts, &out, "vault") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Vault is a free data retrieval call binding the contract method 0xfbfa77cf. -// -// Solidity: function vault() view returns(address) -func (_OutboundQueue *OutboundQueueSession) Vault() (common.Address, error) { - return _OutboundQueue.Contract.Vault(&_OutboundQueue.CallOpts) -} - -// Vault is a free data retrieval call binding the contract method 0xfbfa77cf. -// -// Solidity: function vault() view returns(address) -func (_OutboundQueue *OutboundQueueCallerSession) Vault() (common.Address, error) { - return _OutboundQueue.Contract.Vault(&_OutboundQueue.CallOpts) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.contract.Transact(opts, "grantRole", role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.Contract.GrantRole(&_OutboundQueue.TransactOpts, role, account) -} - -// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. -// -// Solidity: function grantRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.Contract.GrantRole(&_OutboundQueue.TransactOpts, role, account) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.contract.Transact(opts, "renounceRole", role, account) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.Contract.RenounceRole(&_OutboundQueue.TransactOpts, role, account) -} - -// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. -// -// Solidity: function renounceRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueTransactorSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.Contract.RenounceRole(&_OutboundQueue.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.contract.Transact(opts, "revokeRole", role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.Contract.RevokeRole(&_OutboundQueue.TransactOpts, role, account) -} - -// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. -// -// Solidity: function revokeRole(bytes32 role, address account) returns() -func (_OutboundQueue *OutboundQueueTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _OutboundQueue.Contract.RevokeRole(&_OutboundQueue.TransactOpts, role, account) -} - -// Submit is a paid mutator transaction binding the contract method 0xa0397a86. -// -// Solidity: function submit(uint32 dest, bytes payload) payable returns() -func (_OutboundQueue *OutboundQueueTransactor) Submit(opts *bind.TransactOpts, dest uint32, payload []byte) (*types.Transaction, error) { - return _OutboundQueue.contract.Transact(opts, "submit", dest, payload) -} - -// Submit is a paid mutator transaction binding the contract method 0xa0397a86. -// -// Solidity: function submit(uint32 dest, bytes payload) payable returns() -func (_OutboundQueue *OutboundQueueSession) Submit(dest uint32, payload []byte) (*types.Transaction, error) { - return _OutboundQueue.Contract.Submit(&_OutboundQueue.TransactOpts, dest, payload) -} - -// Submit is a paid mutator transaction binding the contract method 0xa0397a86. -// -// Solidity: function submit(uint32 dest, bytes payload) payable returns() -func (_OutboundQueue *OutboundQueueTransactorSession) Submit(dest uint32, payload []byte) (*types.Transaction, error) { - return _OutboundQueue.Contract.Submit(&_OutboundQueue.TransactOpts, dest, payload) -} - -// UpdateFee is a paid mutator transaction binding the contract method 0x9012c4a8. -// -// Solidity: function updateFee(uint256 newFee) returns() -func (_OutboundQueue *OutboundQueueTransactor) UpdateFee(opts *bind.TransactOpts, newFee *big.Int) (*types.Transaction, error) { - return _OutboundQueue.contract.Transact(opts, "updateFee", newFee) -} - -// UpdateFee is a paid mutator transaction binding the contract method 0x9012c4a8. -// -// Solidity: function updateFee(uint256 newFee) returns() -func (_OutboundQueue *OutboundQueueSession) UpdateFee(newFee *big.Int) (*types.Transaction, error) { - return _OutboundQueue.Contract.UpdateFee(&_OutboundQueue.TransactOpts, newFee) -} - -// UpdateFee is a paid mutator transaction binding the contract method 0x9012c4a8. -// -// Solidity: function updateFee(uint256 newFee) returns() -func (_OutboundQueue *OutboundQueueTransactorSession) UpdateFee(newFee *big.Int) (*types.Transaction, error) { - return _OutboundQueue.Contract.UpdateFee(&_OutboundQueue.TransactOpts, newFee) -} - -// OutboundQueueFeeUpdatedIterator is returned from FilterFeeUpdated and is used to iterate over the raw logs and unpacked data for FeeUpdated events raised by the OutboundQueue contract. -type OutboundQueueFeeUpdatedIterator struct { - Event *OutboundQueueFeeUpdated // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *OutboundQueueFeeUpdatedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(OutboundQueueFeeUpdated) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(OutboundQueueFeeUpdated) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *OutboundQueueFeeUpdatedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OutboundQueueFeeUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OutboundQueueFeeUpdated represents a FeeUpdated event raised by the OutboundQueue contract. -type OutboundQueueFeeUpdated struct { - Fee *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterFeeUpdated is a free log retrieval operation binding the contract event 0x8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c76. -// -// Solidity: event FeeUpdated(uint256 fee) -func (_OutboundQueue *OutboundQueueFilterer) FilterFeeUpdated(opts *bind.FilterOpts) (*OutboundQueueFeeUpdatedIterator, error) { - - logs, sub, err := _OutboundQueue.contract.FilterLogs(opts, "FeeUpdated") - if err != nil { - return nil, err - } - return &OutboundQueueFeeUpdatedIterator{contract: _OutboundQueue.contract, event: "FeeUpdated", logs: logs, sub: sub}, nil -} - -// WatchFeeUpdated is a free log subscription operation binding the contract event 0x8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c76. -// -// Solidity: event FeeUpdated(uint256 fee) -func (_OutboundQueue *OutboundQueueFilterer) WatchFeeUpdated(opts *bind.WatchOpts, sink chan<- *OutboundQueueFeeUpdated) (event.Subscription, error) { - - logs, sub, err := _OutboundQueue.contract.WatchLogs(opts, "FeeUpdated") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(OutboundQueueFeeUpdated) - if err := _OutboundQueue.contract.UnpackLog(event, "FeeUpdated", 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 -} - -// ParseFeeUpdated is a log parse operation binding the contract event 0x8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c76. -// -// Solidity: event FeeUpdated(uint256 fee) -func (_OutboundQueue *OutboundQueueFilterer) ParseFeeUpdated(log types.Log) (*OutboundQueueFeeUpdated, error) { - event := new(OutboundQueueFeeUpdated) - if err := _OutboundQueue.contract.UnpackLog(event, "FeeUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// OutboundQueueMessageIterator is returned from FilterMessage and is used to iterate over the raw logs and unpacked data for Message events raised by the OutboundQueue contract. -type OutboundQueueMessageIterator struct { - Event *OutboundQueueMessage // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *OutboundQueueMessageIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(OutboundQueueMessage) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(OutboundQueueMessage) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *OutboundQueueMessageIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OutboundQueueMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OutboundQueueMessage represents a Message event raised by the OutboundQueue contract. -type OutboundQueueMessage struct { - Dest uint32 - Nonce uint64 - Payload []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterMessage is a free log retrieval operation binding the contract event 0x1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad. -// -// Solidity: event Message(uint32 indexed dest, uint64 indexed nonce, bytes payload) -func (_OutboundQueue *OutboundQueueFilterer) FilterMessage(opts *bind.FilterOpts, dest []uint32, nonce []uint64) (*OutboundQueueMessageIterator, error) { - - var destRule []interface{} - for _, destItem := range dest { - destRule = append(destRule, destItem) - } - var nonceRule []interface{} - for _, nonceItem := range nonce { - nonceRule = append(nonceRule, nonceItem) - } - - logs, sub, err := _OutboundQueue.contract.FilterLogs(opts, "Message", destRule, nonceRule) - if err != nil { - return nil, err - } - return &OutboundQueueMessageIterator{contract: _OutboundQueue.contract, event: "Message", logs: logs, sub: sub}, nil -} - -// WatchMessage is a free log subscription operation binding the contract event 0x1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad. -// -// Solidity: event Message(uint32 indexed dest, uint64 indexed nonce, bytes payload) -func (_OutboundQueue *OutboundQueueFilterer) WatchMessage(opts *bind.WatchOpts, sink chan<- *OutboundQueueMessage, dest []uint32, nonce []uint64) (event.Subscription, error) { - - var destRule []interface{} - for _, destItem := range dest { - destRule = append(destRule, destItem) - } - var nonceRule []interface{} - for _, nonceItem := range nonce { - nonceRule = append(nonceRule, nonceItem) - } - - logs, sub, err := _OutboundQueue.contract.WatchLogs(opts, "Message", destRule, nonceRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(OutboundQueueMessage) - if err := _OutboundQueue.contract.UnpackLog(event, "Message", 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 -} - -// ParseMessage is a log parse operation binding the contract event 0x1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad. -// -// Solidity: event Message(uint32 indexed dest, uint64 indexed nonce, bytes payload) -func (_OutboundQueue *OutboundQueueFilterer) ParseMessage(log types.Log) (*OutboundQueueMessage, error) { - event := new(OutboundQueueMessage) - if err := _OutboundQueue.contract.UnpackLog(event, "Message", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// OutboundQueueRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the OutboundQueue contract. -type OutboundQueueRoleAdminChangedIterator struct { - Event *OutboundQueueRoleAdminChanged // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *OutboundQueueRoleAdminChangedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(OutboundQueueRoleAdminChanged) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(OutboundQueueRoleAdminChanged) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *OutboundQueueRoleAdminChangedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OutboundQueueRoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OutboundQueueRoleAdminChanged represents a RoleAdminChanged event raised by the OutboundQueue contract. -type OutboundQueueRoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_OutboundQueue *OutboundQueueFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*OutboundQueueRoleAdminChangedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _OutboundQueue.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return &OutboundQueueRoleAdminChangedIterator{contract: _OutboundQueue.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil -} - -// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_OutboundQueue *OutboundQueueFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *OutboundQueueRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _OutboundQueue.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(OutboundQueueRoleAdminChanged) - if err := _OutboundQueue.contract.UnpackLog(event, "RoleAdminChanged", 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 -} - -// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. -// -// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) -func (_OutboundQueue *OutboundQueueFilterer) ParseRoleAdminChanged(log types.Log) (*OutboundQueueRoleAdminChanged, error) { - event := new(OutboundQueueRoleAdminChanged) - if err := _OutboundQueue.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// OutboundQueueRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the OutboundQueue contract. -type OutboundQueueRoleGrantedIterator struct { - Event *OutboundQueueRoleGranted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *OutboundQueueRoleGrantedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(OutboundQueueRoleGranted) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(OutboundQueueRoleGranted) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *OutboundQueueRoleGrantedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OutboundQueueRoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OutboundQueueRoleGranted represents a RoleGranted event raised by the OutboundQueue contract. -type OutboundQueueRoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_OutboundQueue *OutboundQueueFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*OutboundQueueRoleGrantedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _OutboundQueue.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &OutboundQueueRoleGrantedIterator{contract: _OutboundQueue.contract, event: "RoleGranted", logs: logs, sub: sub}, nil -} - -// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_OutboundQueue *OutboundQueueFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *OutboundQueueRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _OutboundQueue.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(OutboundQueueRoleGranted) - if err := _OutboundQueue.contract.UnpackLog(event, "RoleGranted", 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 -} - -// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. -// -// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) -func (_OutboundQueue *OutboundQueueFilterer) ParseRoleGranted(log types.Log) (*OutboundQueueRoleGranted, error) { - event := new(OutboundQueueRoleGranted) - if err := _OutboundQueue.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// OutboundQueueRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the OutboundQueue contract. -type OutboundQueueRoleRevokedIterator struct { - Event *OutboundQueueRoleRevoked // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *OutboundQueueRoleRevokedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(OutboundQueueRoleRevoked) - 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 - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(OutboundQueueRoleRevoked) - 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() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *OutboundQueueRoleRevokedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *OutboundQueueRoleRevokedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// OutboundQueueRoleRevoked represents a RoleRevoked event raised by the OutboundQueue contract. -type OutboundQueueRoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_OutboundQueue *OutboundQueueFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*OutboundQueueRoleRevokedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _OutboundQueue.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &OutboundQueueRoleRevokedIterator{contract: _OutboundQueue.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil -} - -// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_OutboundQueue *OutboundQueueFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *OutboundQueueRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _OutboundQueue.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(OutboundQueueRoleRevoked) - if err := _OutboundQueue.contract.UnpackLog(event, "RoleRevoked", 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 -} - -// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. -// -// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) -func (_OutboundQueue *OutboundQueueFilterer) ParseRoleRevoked(log types.Log) (*OutboundQueueRoleRevoked, error) { - event := new(OutboundQueueRoleRevoked) - if err := _OutboundQueue.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/relays/beacon/header/syncer/sync_protocol_test.go b/relayer/relays/beacon/header/syncer/sync_protocol_test.go index 31c1bfc4cd45f..53e16486d5bff 100644 --- a/relayer/relays/beacon/header/syncer/sync_protocol_test.go +++ b/relayer/relays/beacon/header/syncer/sync_protocol_test.go @@ -35,7 +35,7 @@ func TestIsStartOfEpoch(t *testing.T) { } syncer := Syncer{} - syncer.SlotsInEpoch = 32 + syncer.setting.SlotsInEpoch = 32 for _, tt := range values { result := syncer.IsStartOfEpoch(tt.slot) diff --git a/relayer/relays/beacon/header/syncer/syncer_test.go b/relayer/relays/beacon/header/syncer/syncer_test.go index c9b0642985e4d..5b2db15b04e48 100644 --- a/relayer/relays/beacon/header/syncer/syncer_test.go +++ b/relayer/relays/beacon/header/syncer/syncer_test.go @@ -30,8 +30,8 @@ func TestCalculateNextCheckpointSlot(t *testing.T) { } syncer := Syncer{} - syncer.SlotsInEpoch = 8 - syncer.EpochsPerSyncCommitteePeriod = 8 + syncer.setting.SlotsInEpoch = 8 + syncer.setting.EpochsPerSyncCommitteePeriod = 8 for _, tt := range values { result := syncer.CalculateNextCheckpointSlot(tt.slot) diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index 6e42ba00cc342..4e656c4e690f1 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -3,14 +3,11 @@ package beefy import ( "context" "encoding/hex" - "errors" "fmt" "math/big" - "time" "golang.org/x/sync/errgroup" - goEthereum "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -81,45 +78,6 @@ func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, request return nil } -func (wr *EthereumWriter) waitForTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { - for { - receipt, err := wr.pollTransaction(ctx, tx, confirmations) - if err != nil { - return nil, err - } - - if receipt != nil { - return receipt, nil - } - - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-time.After(500 * time.Millisecond): - } - } -} - -func (wr *EthereumWriter) pollTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { - receipt, err := wr.conn.Client().TransactionReceipt(ctx, tx.Hash()) - if err != nil { - if errors.Is(err, goEthereum.NotFound) { - return nil, nil - } - } - - latestHeader, err := wr.conn.Client().HeaderByNumber(ctx, nil) - if err != nil { - return nil, err - } - - if latestHeader.Number.Uint64()-receipt.BlockNumber.Uint64() >= confirmations { - return receipt, nil - } - - return nil, nil -} - func (wr *EthereumWriter) submit(ctx context.Context, task Request) error { // Initial submission tx, initialBitfield, err := wr.doSubmitInitial(ctx, &task) @@ -130,14 +88,11 @@ func (wr *EthereumWriter) submit(ctx context.Context, task Request) error { // Wait RandaoCommitDelay before submit CommitPrevRandao to prevent attacker from manipulating committee memberships // Details in https://eth2book.info/altair/part3/config/preset/#max_seed_lookahead - receipt, err := wr.waitForTransaction(ctx, tx, wr.blockWaitPeriod+1) + _, err = wr.conn.WatchTransaction(ctx, tx, wr.blockWaitPeriod+1) if err != nil { log.WithError(err).Error("Failed to wait for RandaoCommitDelay") return err } - if receipt.Status != 1 { - return fmt.Errorf("initial commitment transaction failed, status (%v), logs (%v)", receipt.Status, receipt.Logs) - } commitmentHash, err := task.CommitmentHash() if err != nil { @@ -145,18 +100,16 @@ func (wr *EthereumWriter) submit(ctx context.Context, task Request) error { } // Commit PrevRandao which will be used as seed to randomly select subset of validators - // https://github.com/Snowfork/snowbridge/blob/75a475cbf8fc8e13577ad6b773ac452b2bf82fbb/core/packages/contracts/contracts/BeefyClient.sol#L446-L447 + // https://github.com/Snowfork/snowbridge/blob/75a475cbf8fc8e13577ad6b773ac452b2bf82fbb/contracts/contracts/BeefyClient.sol#L446-L447 tx, err = wr.contract.CommitPrevRandao( - wr.makeTxOpts(ctx), + wr.conn.MakeTxOpts(ctx), *commitmentHash, ) - receipt, err = wr.waitForTransaction(ctx, tx, 1) + _, err = wr.conn.WatchTransaction(ctx, tx, 1) if err != nil { + log.WithError(err).Error("Failed to CommitPrevRandao") return err } - if receipt.Status != 1 { - return fmt.Errorf("commitmentPrevRandao transaction failed") - } // Final submission tx, err = wr.doSubmitFinal(ctx, *commitmentHash, initialBitfield, &task) @@ -165,12 +118,10 @@ func (wr *EthereumWriter) submit(ctx context.Context, task Request) error { return err } - success, err := wr.watchTransaction(ctx, tx, 0) + _, err = wr.conn.WatchTransaction(ctx, tx, 0) if err != nil { - return fmt.Errorf("monitoring failed for transaction SubmitFinal (%v): %w", tx.Hash().Hex(), err) - } - if !success { - return fmt.Errorf("transaction SubmitFinal failed (%v), handover (%v)", tx.Hash().Hex(), task.IsHandover) + log.WithError(err).Error("Failed to submitFinal") + return err } log.WithFields(logrus.Fields{"tx": tx.Hash().Hex(), "handover": task.IsHandover, "blockNumber": task.SignedCommitment.Commitment.BlockNumber}).Debug("Transaction SubmitFinal succeeded") @@ -179,45 +130,6 @@ func (wr *EthereumWriter) submit(ctx context.Context, task Request) error { } -func (wr *EthereumWriter) watchTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (bool, error) { - receipt, err := wr.waitForTransaction(ctx, tx, confirmations) - if err != nil { - return false, err - } - return receipt.Status == 1, nil -} - -func (wr *EthereumWriter) makeTxOpts(ctx context.Context) *bind.TransactOpts { - chainID := wr.conn.ChainID() - keypair := wr.conn.Keypair() - - options := bind.TransactOpts{ - From: keypair.CommonAddress(), - Signer: func(_ common.Address, tx *types.Transaction) (*types.Transaction, error) { - return types.SignTx(tx, types.NewLondonSigner(chainID), keypair.PrivateKey()) - }, - Context: ctx, - } - - if wr.config.Ethereum.GasFeeCap > 0 { - fee := big.NewInt(0) - fee.SetUint64(wr.config.Ethereum.GasFeeCap) - options.GasFeeCap = fee - } - - if wr.config.Ethereum.GasTipCap > 0 { - tip := big.NewInt(0) - tip.SetUint64(wr.config.Ethereum.GasTipCap) - options.GasTipCap = tip - } - - if wr.config.Ethereum.GasLimit > 0 { - options.GasLimit = wr.config.Ethereum.GasLimit - } - - return &options -} - func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (*types.Transaction, []*big.Int, error) { signedValidators := []*big.Int{} for i, signature := range task.SignedCommitment.Signatures { @@ -247,7 +159,7 @@ func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (* var tx *types.Transaction if task.IsHandover { tx, err = wr.contract.SubmitInitialWithHandover( - wr.makeTxOpts(ctx), + wr.conn.MakeTxOpts(ctx), msg.Commitment, msg.Bitfield, msg.Proof, @@ -257,7 +169,7 @@ func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (* } } else { tx, err = wr.contract.SubmitInitial( - wr.makeTxOpts(ctx), + wr.conn.MakeTxOpts(ctx), msg.Commitment, msg.Bitfield, msg.Proof, @@ -313,9 +225,9 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] // In Handover mode except for the validator proof to verify commitment signature // will also add mmr leaf proof which contains nextAuthoritySet to verify against mmr root - // https://github.com/Snowfork/snowbridge/blob/75a475cbf8fc8e13577ad6b773ac452b2bf82fbb/core/packages/contracts/contracts/BeefyClient.sol#L342-L350 + // https://github.com/Snowfork/snowbridge/blob/75a475cbf8fc8e13577ad6b773ac452b2bf82fbb/contracts/contracts/BeefyClient.sol#L342-L350 tx, err := wr.contract.SubmitFinalWithHandover( - wr.makeTxOpts(ctx), + wr.conn.MakeTxOpts(ctx), params.Commitment, params.Bitfield, params.Proofs, @@ -339,7 +251,7 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] } tx, err := wr.contract.SubmitFinal( - wr.makeTxOpts(ctx), + wr.conn.MakeTxOpts(ctx), params.Commitment, params.Bitfield, params.Proofs, diff --git a/relayer/relays/beefy/main.go b/relayer/relays/beefy/main.go index 3b1c88d7dff75..af7a6b9fac4f9 100644 --- a/relayer/relays/beefy/main.go +++ b/relayer/relays/beefy/main.go @@ -26,7 +26,7 @@ type Relay struct { func NewRelay(config *Config, ethereumKeypair *secp256k1.Keypair) (*Relay, error) { relaychainConn := relaychain.NewConnection(config.Source.Polkadot.Endpoint) - ethereumConn := ethereum.NewConnection(config.Sink.Ethereum.Endpoint, ethereumKeypair) + ethereumConn := ethereum.NewConnection(&config.Sink.Ethereum, ethereumKeypair) polkadotListener := NewPolkadotListener( &config.Source, diff --git a/relayer/relays/beefy/task_test.go b/relayer/relays/beefy/task_test.go index da48479893e47..336e066a61d28 100644 --- a/relayer/relays/beefy/task_test.go +++ b/relayer/relays/beefy/task_test.go @@ -1,11 +1,7 @@ package beefy import ( - "fmt" - "testing" - "github.com/snowfork/go-substrate-rpc-client/v4/types" - "github.com/stretchr/testify/assert" ) func makeCommitment() (*types.Commitment, error) { @@ -29,18 +25,3 @@ func makeCommitment() (*types.Commitment, error) { return &commitment, nil } - -func TestCommitment_Split(t *testing.T) { - c, err := makeCommitment() - assert.NoError(t, err) - - payload, err := buildPayload(c.Payload) - assert.NoError(t, err) - - fmt.Printf("mmrroothash: %s\n", types.HexEncodeToString(payload.MmrRootHash[:])) - fmt.Printf("prefix: %s\n", types.HexEncodeToString(payload.Prefix)) - fmt.Printf("suffix: %s\n", types.HexEncodeToString(payload.Suffix)) - - commitmentBytes, _ := types.EncodeToHexString(c) - fmt.Println(commitmentBytes) -} diff --git a/relayer/relays/execution/config.go b/relayer/relays/execution/config.go index b2ebcf2cfb726..8772f465b5bcb 100644 --- a/relayer/relays/execution/config.go +++ b/relayer/relays/execution/config.go @@ -12,13 +12,11 @@ type Config struct { type SourceConfig struct { Ethereum config.EthereumConfig `mapstructure:"ethereum"` Contracts ContractsConfig `mapstructure:"contracts"` - LaneID uint32 `mapstructure:"lane-id"` + ChannelID uint32 `mapstructure:"channel-id"` } -type Address []byte - type ContractsConfig struct { - OutboundQueue string `mapstructure:"OutboundQueue"` + Gateway string `mapstructure:"Gateway"` } type SinkConfig struct { diff --git a/relayer/relays/execution/main.go b/relayer/relays/execution/main.go index c304dd0c0e5db..2519b88837ff4 100644 --- a/relayer/relays/execution/main.go +++ b/relayer/relays/execution/main.go @@ -20,11 +20,11 @@ import ( ) type Relay struct { - config *Config - keypair *sr25519.Keypair - paraconn *parachain.Connection - ethconn *ethereum.Connection - outboundQueueContract *contracts.OutboundQueue + config *Config + keypair *sr25519.Keypair + paraconn *parachain.Connection + ethconn *ethereum.Connection + gatewayContract *contracts.Gateway } func NewRelay( @@ -39,7 +39,7 @@ func NewRelay( func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { paraconn := parachain.NewConnection(r.config.Sink.Parachain.Endpoint, r.keypair.AsKeyringPair()) - ethconn := ethereum.NewConnection(r.config.Source.Ethereum.Endpoint, nil) + ethconn := ethereum.NewConnection(&r.config.Source.Ethereum, nil) err := paraconn.Connect(ctx) if err != nil { @@ -71,19 +71,21 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { return err } - address := common.HexToAddress(r.config.Source.Contracts.OutboundQueue) - contract, err := contracts.NewOutboundQueue(address, ethconn.Client()) + address := common.HexToAddress(r.config.Source.Contracts.Gateway) + contract, err := contracts.NewGateway(address, ethconn.Client()) if err != nil { return err } - r.outboundQueueContract = contract + r.gatewayContract = contract for { select { case <-ctx.Done(): return nil case <-time.After(12 * time.Second): - log.Info("Polling") + log.WithFields(log.Fields{ + "channelId": r.config.Source.ChannelID, + }).Info("Polling Nonces") executionHeaderState, err := writer.GetLastExecutionHeaderState() if err != nil { @@ -95,6 +97,13 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { return err } + if executionHeaderState.BlockNumber == 0 { + log.WithFields(log.Fields{ + "channelId": r.config.Source.ChannelID, + }).Info("Beacon execution state syncing not started, waiting...") + continue + } + ethNonce, err := r.fetchEthereumNonce(ctx, executionHeaderState.BlockNumber) if err != nil { return err @@ -102,7 +111,7 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { log.WithFields(log.Fields{ "ethBlockNumber": executionHeaderState.BlockNumber, - "laneId": r.config.Source.LaneID, + "channelId": r.config.Source.ChannelID, "paraNonce": paraNonce, "ethNonce": ethNonce, }).Info("Polled Nonces") @@ -112,25 +121,50 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error { } events, err := r.findEvents(ctx, executionHeaderState.BlockNumber, paraNonce+1) + if err != nil { + return fmt.Errorf("find events: %w", err) + } for _, ev := range events { inboundMsg, err := r.makeInboundMessage(ctx, headerCache, ev) if err != nil { return fmt.Errorf("make outgoing message: %w", err) } + logger := log.WithFields(log.Fields{ + "paraNonce": paraNonce, + "ethNonce": ethNonce, + "msgNonce": ev.Nonce, + "address": ev.Raw.Address.Hex(), + "blockHash": ev.Raw.BlockHash.Hex(), + "blockNumber": ev.Raw.BlockNumber, + "txHash": ev.Raw.TxHash.Hex(), + "dest": ev.Destination, + }) + + if ev.Nonce <= paraNonce { + logger.Warn("inbound message outdated, just skipped") + continue + } err = writer.WriteToParachainAndWatch(ctx, "EthereumInboundQueue.submit", inboundMsg) if err != nil { + logger.Error("inbound message fail to sent") return fmt.Errorf("write to parachain: %w", err) } + paraNonce, _ = r.fetchLatestParachainNonce() + if paraNonce != ev.Nonce { + logger.Error("inbound message sent but fail to execute") + return fmt.Errorf("inbound message fail to execute") + } + logger.Info("inbound message executed successfully") } } } } func (r *Relay) fetchLatestParachainNonce() (uint64, error) { - paraID := r.config.Source.LaneID - encodedParaID, err := types.EncodeToBytes(r.config.Source.LaneID) + paraID := r.config.Source.ChannelID + encodedParaID, err := types.EncodeToBytes(r.config.Source.ChannelID) if err != nil { return 0, err } @@ -159,21 +193,25 @@ func (r *Relay) fetchEthereumNonce(ctx context.Context, blockNumber uint64) (uin BlockNumber: new(big.Int).SetUint64(blockNumber), Context: ctx, } - nonce, err := r.outboundQueueContract.Nonce(&opts, r.config.Source.LaneID) + _, ethOutboundNonce, err := r.gatewayContract.ChannelNoncesOf(&opts, big.NewInt(int64(r.config.Source.ChannelID))) if err != nil { - return 0, fmt.Errorf("fetch OutboundQueue.Nonce(%v): %w", r.config.Source.LaneID, err) + return 0, fmt.Errorf("fetch Gateway.ChannelNoncesOf(%v): %w", r.config.Source.ChannelID, err) } - return nonce, nil + return ethOutboundNonce, nil } const BlocksPerQuery = 4096 -func (r *Relay) findEvents(ctx context.Context, latestFinalizedBlockNumber uint64, start uint64) ([]*contracts.OutboundQueueMessage, error) { +func (r *Relay) findEvents( + ctx context.Context, + latestFinalizedBlockNumber uint64, + start uint64, +) ([]*contracts.GatewayOutboundMessageAccepted, error) { - paraID := r.config.Source.LaneID + paraID := r.config.Source.ChannelID - var allEvents []*contracts.OutboundQueueMessage + var allEvents []*contracts.GatewayOutboundMessageAccepted blockNumber := latestFinalizedBlockNumber @@ -216,13 +254,13 @@ func (r *Relay) findEvents(ctx context.Context, latestFinalizedBlockNumber uint6 return allEvents, nil } -func (r *Relay) findEventsWithFilter(opts *bind.FilterOpts, paraID uint32, start uint64) (bool, []*contracts.OutboundQueueMessage, error) { - iter, err := r.outboundQueueContract.FilterMessage(opts, []uint32{paraID}, []uint64{}) +func (r *Relay) findEventsWithFilter(opts *bind.FilterOpts, paraID uint32, start uint64) (bool, []*contracts.GatewayOutboundMessageAccepted, error) { + iter, err := r.gatewayContract.FilterOutboundMessageAccepted(opts, []*big.Int{big.NewInt(int64(paraID))}) if err != nil { return false, nil, err } - var events []*contracts.OutboundQueueMessage + var events []*contracts.GatewayOutboundMessageAccepted done := false for { @@ -234,9 +272,10 @@ func (r *Relay) findEventsWithFilter(opts *bind.FilterOpts, paraID uint32, start } break } - - events = append(events, iter.Event) - if iter.Event.Nonce == start { + if iter.Event.Nonce >= start { + events = append(events, iter.Event) + } + if iter.Event.Nonce == start && opts.Start != 0 { done = true iter.Close() break @@ -249,7 +288,7 @@ func (r *Relay) findEventsWithFilter(opts *bind.FilterOpts, paraID uint32, start func (r *Relay) makeInboundMessage( ctx context.Context, headerCache *ethereum.HeaderCache, - event *contracts.OutboundQueueMessage, + event *contracts.GatewayOutboundMessageAccepted, ) (*parachain.Message, error) { receiptTrie, err := headerCache.GetReceiptTrie(ctx, event.Raw.BlockHash) if err != nil { diff --git a/relayer/relays/parachain/config.go b/relayer/relays/parachain/config.go index deb2e872d057c..59140cd918d91 100644 --- a/relayer/relays/parachain/config.go +++ b/relayer/relays/parachain/config.go @@ -9,17 +9,18 @@ type Config struct { Sink SinkConfig `mapstructure:"sink"` } +// TODO: check whether ChannelID should be uint32 (as in the parachain) or big.Int (uint256, as in the Gateway contract) type SourceConfig struct { Polkadot config.PolkadotConfig `mapstructure:"polkadot"` Parachain config.ParachainConfig `mapstructure:"parachain"` Ethereum config.EthereumConfig `mapstructure:"ethereum"` Contracts SourceContractsConfig `mapstructure:"contracts"` - LaneID uint32 `mapstructure:"lane-id"` + ChannelID uint32 `mapstructure:"channel-id"` } type SourceContractsConfig struct { - BeefyClient string `mapstructure:"BeefyClient"` - InboundQueue string `mapstructure:"InboundQueue"` + BeefyClient string `mapstructure:"BeefyClient"` + Gateway string `mapstructure:"Gateway"` } type SinkConfig struct { @@ -28,5 +29,5 @@ type SinkConfig struct { } type SinkContractsConfig struct { - InboundQueue string `mapstructure:"InboundQueue"` + Gateway string `mapstructure:"Gateway"` } diff --git a/relayer/relays/parachain/ethereum-writer.go b/relayer/relays/parachain/ethereum-writer.go index 6fe39daba28e4..61856dd58b53d 100644 --- a/relayer/relays/parachain/ethereum-writer.go +++ b/relayer/relays/parachain/ethereum-writer.go @@ -7,14 +7,12 @@ import ( "fmt" "math/big" "strings" - "time" "golang.org/x/sync/errgroup" "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/snowfork/snowbridge/relayer/chain/ethereum" "github.com/snowfork/snowbridge/relayer/contracts" @@ -22,19 +20,15 @@ import ( gsrpcTypes "github.com/snowfork/go-substrate-rpc-client/v4/types" - goEthereum "github.com/ethereum/go-ethereum" - log "github.com/sirupsen/logrus" ) type EthereumWriter struct { - config *SinkConfig - conn *ethereum.Connection - inboundQueue *contracts.InboundQueue - tasks <-chan *Task - abiPacker abi.Arguments - abiBasicUnpacker abi.Arguments - inboundQueueABI abi.ABI + config *SinkConfig + conn *ethereum.Connection + gateway *contracts.Gateway + tasks <-chan *Task + gatewayABI abi.ABI } func NewEthereumWriter( @@ -43,33 +37,26 @@ func NewEthereumWriter( tasks <-chan *Task, ) (*EthereumWriter, error) { return &EthereumWriter{ - config: config, - conn: conn, - inboundQueue: nil, - tasks: tasks, + config: config, + conn: conn, + gateway: nil, + tasks: tasks, }, nil } func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group) error { - address := common.HexToAddress(wr.config.Contracts.InboundQueue) - basicChannel, err := contracts.NewInboundQueue(address, wr.conn.Client()) + address := common.HexToAddress(wr.config.Contracts.Gateway) + gateway, err := contracts.NewGateway(address, wr.conn.Client()) if err != nil { return err } - wr.inboundQueue = basicChannel + wr.gateway = gateway - opaqueProofABI, err := abi.JSON(strings.NewReader(contracts.OpaqueProofABI)) + gatewayABI, err := abi.JSON(strings.NewReader(contracts.GatewayABI)) if err != nil { return err } - wr.abiPacker = opaqueProofABI.Methods["dummy"].Inputs - - inboundQueueABI, err := abi.JSON(strings.NewReader(contracts.InboundQueueABI)) - if err != nil { - return err - } - wr.inboundQueueABI = inboundQueueABI - wr.abiBasicUnpacker = abi.Arguments{inboundQueueABI.Methods["submit"].Inputs[0]} + wr.gatewayABI = gatewayABI eg.Go(func() error { err := wr.writeMessagesLoop(ctx) @@ -85,39 +72,8 @@ func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group) error { return nil } -func (wr *EthereumWriter) makeTxOpts(ctx context.Context) *bind.TransactOpts { - chainID := wr.conn.ChainID() - keypair := wr.conn.Keypair() - - options := bind.TransactOpts{ - From: keypair.CommonAddress(), - Signer: func(_ common.Address, tx *types.Transaction) (*types.Transaction, error) { - return types.SignTx(tx, types.NewLondonSigner(chainID), keypair.PrivateKey()) - }, - Context: ctx, - } - - if wr.config.Ethereum.GasFeeCap > 0 { - fee := big.NewInt(0) - fee.SetUint64(wr.config.Ethereum.GasFeeCap) - options.GasFeeCap = fee - } - - if wr.config.Ethereum.GasTipCap > 0 { - tip := big.NewInt(0) - tip.SetUint64(wr.config.Ethereum.GasTipCap) - options.GasTipCap = tip - } - - if wr.config.Ethereum.GasLimit > 0 { - options.GasLimit = wr.config.Ethereum.GasLimit - } - - return &options -} - func (wr *EthereumWriter) writeMessagesLoop(ctx context.Context) error { - options := wr.makeTxOpts(ctx) + options := wr.conn.MakeTxOpts(ctx) for { select { case <-ctx.Done(): @@ -139,10 +95,10 @@ func (wr *EthereumWriter) WriteChannels( options *bind.TransactOpts, task *Task, ) error { - for _, proof := range *task.BasicChannelProofs { + for _, proof := range *task.MessageProofs { err := wr.WriteChannel(ctx, options, &proof, task.ProofOutput) if err != nil { - return fmt.Errorf("write basic channel: %w", err) + return fmt.Errorf("write eth gateway: %w", err) } } @@ -158,10 +114,9 @@ func (wr *EthereumWriter) WriteChannel( ) error { message := commitmentProof.Message.IntoInboundMessage() - paraHeadProof := contracts.ParachainClientHeadProof{ - Pos: big.NewInt(int64(proof.MerkleProofData.ProvenLeafIndex)), - Width: big.NewInt(int64(proof.MerkleProofData.NumberOfLeaves)), - Proof: proof.MerkleProofData.Proof, + convertedHeader, err := convertHeader(proof.Header) + if err != nil { + return fmt.Errorf("convert header: %w", err) } var merkleProofItems [][32]byte @@ -169,15 +124,14 @@ func (wr *EthereumWriter) WriteChannel( merkleProofItems = append(merkleProofItems, proofItem) } - convertedHeader, err := convertHeader(proof.Header) - if err != nil { - return fmt.Errorf("convert header: %w", err) - } - - finalProof := contracts.ParachainClientProof{ - Header: *convertedHeader, - HeadProof: paraHeadProof, - LeafPartial: contracts.ParachainClientMMRLeafPartial{ + verificationProof := contracts.VerificationProof{ + Header: *convertedHeader, + HeadProof: contracts.VerificationHeadProof{ + Pos: big.NewInt(proof.MerkleProofData.ProvenLeafIndex), + Width: big.NewInt(int64(proof.MerkleProofData.NumberOfLeaves)), + Proof: proof.MerkleProofData.Proof, + }, + LeafPartial: contracts.VerificationMMRLeafPartial{ Version: uint8(proof.MMRProof.Leaf.Version), ParentNumber: uint32(proof.MMRProof.Leaf.ParentNumberAndHash.ParentNumber), ParentHash: proof.MMRProof.Leaf.ParentNumberAndHash.Hash, @@ -189,16 +143,11 @@ func (wr *EthereumWriter) WriteChannel( LeafProofOrder: new(big.Int).SetUint64(proof.MMRProof.MerkleProofOrder), } - opaqueProof, err := wr.abiPacker.Pack(finalProof) - if err != nil { - return fmt.Errorf("pack proof: %w", err) - } - - tx, err := wr.inboundQueue.Submit( - options, message, commitmentProof.Proof.InnerHashes, opaqueProof, + tx, err := wr.gateway.SubmitInbound( + options, message, commitmentProof.Proof.InnerHashes, verificationProof, ) if err != nil { - return fmt.Errorf("send transaction InboundQueue.submit: %w", err) + return fmt.Errorf("send transaction Gateway.submit: %w", err) } hasher := &keccak.Keccak256{} @@ -207,7 +156,7 @@ func (wr *EthereumWriter) WriteChannel( return fmt.Errorf("encode MMRLeaf: %w", err) } log.WithField("txHash", tx.Hash().Hex()). - WithField("params", wr.logFieldsForSubmission(message, commitmentProof.Proof.InnerHashes, opaqueProof)). + WithField("params", wr.logFieldsForSubmission(message, commitmentProof.Proof.InnerHashes, verificationProof)). WithFields(log.Fields{ "commitmentHash": commitmentProof.Proof.Root.Hex(), "MMRRoot": proof.MMRRootHash.Hex(), @@ -217,25 +166,26 @@ func (wr *EthereumWriter) WriteChannel( "beefyBlock": proof.MMRProof.Blockhash.Hex(), "header": proof.Header, }). - Info("Sent transaction InboundQueue.submit") + Info("Sent transaction Gateway.submit") - receipt, err := wr.waitForTransaction(ctx, tx, 1) + receipt, err := wr.conn.WatchTransaction(ctx, tx, 1) - if receipt.Status != 1 { - return fmt.Errorf("transaction failed: %s", receipt.TxHash.Hex()) + if err != nil { + log.WithError(err).Error("Failed to SubmitInbound") + return err } for _, ev := range receipt.Logs { - if ev.Topics[0] == wr.inboundQueueABI.Events["MessageDispatched"].ID { - var holder contracts.InboundQueueMessageDispatched - err = wr.inboundQueueABI.UnpackIntoInterface(&holder, "MessageDispatched", ev.Data) + if ev.Topics[0] == wr.gatewayABI.Events["InboundMessageDispatched"].ID { + var holder contracts.GatewayInboundMessageDispatched + err = wr.gatewayABI.UnpackIntoInterface(&holder, "InboundMessageDispatched", ev.Data) if err != nil { return fmt.Errorf("unpack event log: %w", err) } log.WithFields(log.Fields{ - "origin": holder.Origin, - "nonce": holder.Nonce, - "result": holder.Result, + "origin": holder.Origin, + "nonce": holder.Nonce, + "success": holder.Success, }).Info("Message dispatched") } } @@ -243,20 +193,20 @@ func (wr *EthereumWriter) WriteChannel( return nil } -func convertHeader(header gsrpcTypes.Header) (*contracts.ParachainClientParachainHeader, error) { - var digestItems []contracts.ParachainClientDigestItem +func convertHeader(header gsrpcTypes.Header) (*contracts.VerificationParachainHeader, error) { + var digestItems []contracts.VerificationDigestItem for _, di := range header.Digest { switch { case di.IsOther: - digestItems = append(digestItems, contracts.ParachainClientDigestItem{ + digestItems = append(digestItems, contracts.VerificationDigestItem{ Kind: big.NewInt(0), Data: di.AsOther, }) case di.IsPreRuntime: consensusEngineID := make([]byte, 4) binary.LittleEndian.PutUint32(consensusEngineID, uint32(di.AsPreRuntime.ConsensusEngineID)) - digestItems = append(digestItems, contracts.ParachainClientDigestItem{ + digestItems = append(digestItems, contracts.VerificationDigestItem{ Kind: big.NewInt(6), ConsensusEngineID: *(*[4]byte)(consensusEngineID), Data: di.AsPreRuntime.Bytes, @@ -264,7 +214,7 @@ func convertHeader(header gsrpcTypes.Header) (*contracts.ParachainClientParachai case di.IsConsensus: consensusEngineID := make([]byte, 4) binary.LittleEndian.PutUint32(consensusEngineID, uint32(di.AsConsensus.ConsensusEngineID)) - digestItems = append(digestItems, contracts.ParachainClientDigestItem{ + digestItems = append(digestItems, contracts.VerificationDigestItem{ Kind: big.NewInt(4), ConsensusEngineID: *(*[4]byte)(consensusEngineID), Data: di.AsConsensus.Bytes, @@ -272,7 +222,7 @@ func convertHeader(header gsrpcTypes.Header) (*contracts.ParachainClientParachai case di.IsSeal: consensusEngineID := make([]byte, 4) binary.LittleEndian.PutUint32(consensusEngineID, uint32(di.AsSeal.ConsensusEngineID)) - digestItems = append(digestItems, contracts.ParachainClientDigestItem{ + digestItems = append(digestItems, contracts.VerificationDigestItem{ Kind: big.NewInt(5), ConsensusEngineID: *(*[4]byte)(consensusEngineID), Data: di.AsSeal.Bytes, @@ -282,7 +232,7 @@ func convertHeader(header gsrpcTypes.Header) (*contracts.ParachainClientParachai } } - return &contracts.ParachainClientParachainHeader{ + return &contracts.VerificationParachainHeader{ ParentHash: header.ParentHash, Number: big.NewInt(int64(header.Number)), StateRoot: header.StateRoot, @@ -290,42 +240,3 @@ func convertHeader(header gsrpcTypes.Header) (*contracts.ParachainClientParachai DigestItems: digestItems, }, nil } - -func (wr *EthereumWriter) waitForTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { - for { - receipt, err := wr.pollTransaction(ctx, tx, confirmations) - if err != nil { - return nil, err - } - - if receipt != nil { - return receipt, nil - } - - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-time.After(500 * time.Millisecond): - } - } -} - -func (wr *EthereumWriter) pollTransaction(ctx context.Context, tx *types.Transaction, confirmations uint64) (*types.Receipt, error) { - receipt, err := wr.conn.Client().TransactionReceipt(ctx, tx.Hash()) - if err != nil { - if errors.Is(err, goEthereum.NotFound) { - return nil, nil - } - } - - latestHeader, err := wr.conn.Client().HeaderByNumber(ctx, nil) - if err != nil { - return nil, err - } - - if latestHeader.Number.Uint64()-receipt.BlockNumber.Uint64() >= confirmations { - return receipt, nil - } - - return nil, nil -} diff --git a/relayer/relays/parachain/logger.go b/relayer/relays/parachain/logger.go index 70ce6022c7f0f..f2738a6d086ae 100644 --- a/relayer/relays/parachain/logger.go +++ b/relayer/relays/parachain/logger.go @@ -1,6 +1,8 @@ package parachain import ( + "fmt" + log "github.com/sirupsen/logrus" "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/contracts" @@ -11,24 +13,66 @@ func Hex(b []byte) string { } func (wr *EthereumWriter) logFieldsForSubmission( - message contracts.InboundQueueMessage, - leafProof [][32]byte, - proof []byte, + message contracts.InboundMessage, + messageProof [][32]byte, + proof contracts.VerificationProof, ) log.Fields { - leafProofHexes := make([]string, len(leafProof)) - for i, leaf := range leafProof { - leafProofHexes[i] = Hex(leaf[:]) + messageProofHexes := make([]string, len(messageProof)) + for i, proof := range messageProof { + messageProofHexes[i] = Hex(proof[:]) + } + + digestItems := make([]log.Fields, len(proof.Header.DigestItems)) + for i, digestItem := range proof.Header.DigestItems { + digestItems[i] = log.Fields{ + "kind": digestItem.Kind, + "consensusEngineID": digestItem.ConsensusEngineID, + "data": Hex(digestItem.Data), + } + } + + headProofHexes := make([]string, len(proof.HeadProof.Proof)) + for i, proof := range proof.HeadProof.Proof { + headProofHexes[i] = Hex(proof[:]) + } + + mmrLeafProofHexes := make([]string, len(proof.LeafProof)) + for i, proof := range proof.LeafProof { + mmrLeafProofHexes[i] = Hex(proof[:]) } params := log.Fields{ "message": log.Fields{ - "origin": message.Origin, - "nonce": message.Nonce, - "recipient": Hex(message.Recipient[:]), - "payload": Hex(message.Payload), + "origin": message.Origin, + "nonce": message.Nonce, + "command": message.Command, + "params": Hex(message.Params), + }, + "messageProof": messageProofHexes, + "proof": log.Fields{ + "header": log.Fields{ + "parentHash": Hex(proof.Header.ParentHash[:]), + "number": proof.Header.Number, + "stateRoot": Hex(proof.Header.StateRoot[:]), + "extrinsicsRoot": Hex(proof.Header.ExtrinsicsRoot[:]), + "digestItems": digestItems, + }, + "headProof": log.Fields{ + "pos": proof.HeadProof.Pos, + "width": proof.HeadProof.Width, + "proof": headProofHexes, + }, + "leafPartial": log.Fields{ + "version": proof.LeafPartial.Version, + "parentNumber": proof.LeafPartial.ParentNumber, + "parentHash": Hex(proof.LeafPartial.ParentHash[:]), + "nextAuthoritySetID": proof.LeafPartial.NextAuthoritySetID, + "nextAuthoritySetLen": proof.LeafPartial.NextAuthoritySetLen, + "nextAuthoritySetRoot": Hex(proof.LeafPartial.NextAuthoritySetRoot[:]), + }, + "leafProof": mmrLeafProofHexes, + "leafProofOrder": fmt.Sprintf("%b", proof.LeafProofOrder), }, - "leafProof": leafProofHexes, - "proof": Hex(proof), } return params diff --git a/relayer/relays/parachain/main.go b/relayer/relays/parachain/main.go index 341f129dab784..797a237dd11a5 100644 --- a/relayer/relays/parachain/main.go +++ b/relayer/relays/parachain/main.go @@ -29,7 +29,7 @@ func NewRelay(config *Config, keypair *secp256k1.Keypair) (*Relay, error) { relaychainConn := relaychain.NewConnection(config.Source.Polkadot.Endpoint) // TODO: This is used by both the source & sink. They should use separate connections - ethereumConn := ethereum.NewConnection(config.Sink.Ethereum.Endpoint, keypair) + ethereumConn := ethereum.NewConnection(&config.Sink.Ethereum, keypair) // channel for messages from beefy listener to ethereum writer var tasks = make(chan *Task, 1) diff --git a/relayer/relays/parachain/scanner.go b/relayer/relays/parachain/scanner.go index d8544c1285447..219ad4e9a6e74 100644 --- a/relayer/relays/parachain/scanner.go +++ b/relayer/relays/parachain/scanner.go @@ -4,6 +4,7 @@ import ( "context" "encoding/binary" "fmt" + "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -25,7 +26,7 @@ type Scanner struct { tasks chan<- *Task } -// Scans for all parachain message commitments for the configured parachain laneID that need to be relayed and can be +// Scans for all parachain message commitments for the configured parachain channelID that need to be relayed and can be // proven using the MMR root at the specified beefyBlockNumber of the relay chain. // // The algorithm works roughly like this: @@ -69,35 +70,35 @@ func (s *Scanner) findTasks( paraBlock uint64, paraHash types.Hash, ) ([]*Task, error) { - // Fetch latest nonce in ethereum inbound queue - inboundQueueAddress := common.HexToAddress(s.config.Contracts.InboundQueue) - inboundQueueContract, err := contracts.NewInboundQueue( - inboundQueueAddress, + // Fetch latest nonce in ethereum gateway + gatewayAddress := common.HexToAddress(s.config.Contracts.Gateway) + gatewayContract, err := contracts.NewGateway( + gatewayAddress, s.ethConn.Client(), ) if err != nil { - return nil, fmt.Errorf("create inbound queue contract for address '%v': %w", inboundQueueAddress, err) + return nil, fmt.Errorf("create gateway contract for address '%v': %w", gatewayAddress, err) } options := bind.CallOpts{ Pending: true, Context: ctx, } - ethNonce, err := inboundQueueContract.Nonce(&options, s.config.LaneID) + ethInboundNonce, _, err := gatewayContract.ChannelNoncesOf(&options, big.NewInt(int64(s.config.ChannelID))) if err != nil { - return nil, fmt.Errorf("fetch nonce from inbound queue contract for laneID '%v': %w", s.config.LaneID, err) + return nil, fmt.Errorf("fetch nonce from gateway contract for channelID '%v': %w", s.config.ChannelID, err) } log.WithFields(log.Fields{ - "nonce": ethNonce, - "laneID": s.config.LaneID, - }).Info("Checked latest nonce delivered to ethereum inbound queue") + "nonce": ethInboundNonce, + "channelID": s.config.ChannelID, + }).Info("Checked latest nonce delivered to ethereum gateway") // Fetch latest nonce in parachain outbound queue sourceIDBytes := make([]byte, 4) - binary.LittleEndian.PutUint32(sourceIDBytes, s.config.LaneID) + binary.LittleEndian.PutUint32(sourceIDBytes, s.config.ChannelID) paraNonceKey, err := types.CreateStorageKey(s.paraConn.Metadata(), "EthereumOutboundQueue", "Nonce", sourceIDBytes, nil) if err != nil { - return nil, fmt.Errorf("create storage key for parachain outbound queue nonce with laneID '%v': %w", s.config.LaneID, err) + return nil, fmt.Errorf("create storage key for parachain outbound queue nonce with channelID '%v': %w", s.config.ChannelID, err) } var paraNonce types.U64 ok, err := s.paraConn.API().RPC.State.GetStorage(paraNonceKey, ¶Nonce, paraHash) @@ -112,11 +113,11 @@ func (s *Scanner) findTasks( paraNonce = 0 } log.WithFields(log.Fields{ - "nonce": uint64(paraNonce), - "laneID": s.config.LaneID, + "nonce": uint64(paraNonce), + "channelID": s.config.ChannelID, }).Info("Checked latest nonce generated by parachain outbound queue") - if !(uint64(paraNonce) > ethNonce) { + if !(uint64(paraNonce) > ethInboundNonce) { return nil, nil } @@ -125,8 +126,8 @@ func (s *Scanner) findTasks( tasks, err := s.findTasksImpl( ctx, paraBlock, - s.config.LaneID, - ethNonce+1, + s.config.ChannelID, + ethInboundNonce+1, ) if err != nil { return nil, err @@ -137,16 +138,16 @@ func (s *Scanner) findTasks( return tasks, nil } -// Searches for all lost commitments on the basic channel from the given parachain block number backwards -// until it finds the given nonces +// Searches from the given parachain block number backwards on the given channel (landID) for all outstanding +// commitments until it finds the given startingNonce func (s *Scanner) findTasksImpl( - ctx context.Context, + _ context.Context, lastParaBlockNumber uint64, - laneID uint32, + channelID uint32, startingNonce uint64, ) ([]*Task, error) { log.WithFields(log.Fields{ - "laneID": laneID, + "channelID": channelID, "nonce": startingNonce, "latestBlockNumber": lastParaBlockNumber, }).Debug("Searching backwards from latest block on parachain to find block with nonce") @@ -203,7 +204,7 @@ func (s *Scanner) findTasksImpl( blockHash, *commitmentHash, startingNonce, - laneID, + channelID, messages, ) if err != nil { @@ -214,10 +215,10 @@ func (s *Scanner) findTasksImpl( if len(result.proofs) > 0 { task := Task{ - Header: header, - BasicChannelProofs: &result.proofs, - ProofInput: nil, - ProofOutput: nil, + Header: header, + MessageProofs: &result.proofs, + ProofInput: nil, + ProofOutput: nil, } tasks = append(tasks, &task) } @@ -330,7 +331,7 @@ func scanForOutboundQueueProofs( blockHash types.Hash, commitmentHash types.H256, startingNonce uint64, - laneID uint32, + channelID uint32, messages []OutboundQueueMessage, ) (*struct { proofs []MessageProof @@ -359,7 +360,7 @@ func scanForOutboundQueueProofs( for i := len(messages) - 1; i >= 0; i-- { message := messages[i] - if message.Origin != laneID { + if message.Origin != channelID { continue } @@ -368,7 +369,7 @@ func scanForOutboundQueueProofs( // This case will be hit when there are no new messages to relay. if messageNonce < startingNonce { log.Debugf( - "Halting scan for laneID '%v'. Messages not committed yet on outbound channel", + "Halting scan for channelID '%v'. Messages not committed yet on outbound channel", message.Origin, ) scanDone = true @@ -382,7 +383,7 @@ func scanForOutboundQueueProofs( // Check that the merkle root in the proof is the same as the digest hash from the header if messageProof.Proof.Root != commitmentHash { return nil, fmt.Errorf( - "Halting scan for laneID '%v'. Outbound queue proof root '%v' doesn't match digest item's commitment hash '%v'", + "Halting scan for channelID '%v'. Outbound queue proof root '%v' doesn't match digest item's commitment hash '%v'", message.Origin, messageProof.Proof.Root, commitmentHash, diff --git a/relayer/relays/parachain/types.go b/relayer/relays/parachain/types.go index afe694adcf7f3..f9d0e216eb494 100644 --- a/relayer/relays/parachain/types.go +++ b/relayer/relays/parachain/types.go @@ -1,6 +1,8 @@ package parachain import ( + "math/big" + "github.com/snowfork/go-substrate-rpc-client/v4/types" "github.com/snowfork/snowbridge/relayer/chain/relaychain" "github.com/snowfork/snowbridge/relayer/contracts" @@ -16,8 +18,8 @@ type Task struct { ProofInput *ProofInput // Outputs of MMR proof generation ProofOutput *ProofOutput - // Commitments for basic channel - BasicChannelProofs *[]MessageProof + // Proofs for messages from outbound channel on Polkadot + MessageProofs *[]MessageProof } // A ProofInput is data needed to generate a proof of parachain header inclusion @@ -83,16 +85,16 @@ func NewMerkleProof(rawProof RawMerkleProof) (MerkleProof, error) { type OutboundQueueMessage struct { Origin uint32 Nonce uint64 - Gateway [32]byte - Payload []byte + Command uint8 + Params []byte } -func (m OutboundQueueMessage) IntoInboundMessage() contracts.InboundQueueMessage { - return contracts.InboundQueueMessage{ - Origin: m.Origin, - Nonce: m.Nonce, - Recipient: m.Gateway, - Payload: m.Payload, +func (m OutboundQueueMessage) IntoInboundMessage() contracts.InboundMessage { + return contracts.InboundMessage{ + Origin: big.NewInt(int64(m.Origin)), + Nonce: m.Nonce, + Command: m.Command, + Params: m.Params, } } diff --git a/relayer/revive.toml b/relayer/revive.toml index 30852b348a8ae..038829954ef3f 100644 --- a/relayer/revive.toml +++ b/relayer/revive.toml @@ -15,7 +15,6 @@ warningCode = 0 [rule.increment-decrement] [rule.var-naming] [rule.var-declaration] -[rule.package-comments] [rule.range] [rule.receiver-naming] [rule.time-naming] diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100755 index 0000000000000..1bdbf12249f90 --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +git submodule update --init --recursive || true +(cd web && pnpm install) +go install github.com/ferranbt/fastssz/sszgen@latest +ln -sf pre-commit.sh .git/hooks/pre-commit diff --git a/.husky/pre-commit b/scripts/pre-commit.sh similarity index 65% rename from .husky/pre-commit rename to scripts/pre-commit.sh index 6df370484c150..04a9092745f46 100755 --- a/.husky/pre-commit +++ b/scripts/pre-commit.sh @@ -1,22 +1,8 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" +#!/usr/bin/env bash set -e -echo 'Running pre-commit hook...' - -# check typos -chronic typos . - -# lint and format for core contracts and typescript codes -(cd core && chronic pnpm lint && pnpm format) - -# lint and format for relayer codes -(cd relayer && chronic mage lint && chronic go fmt ./...) - -# comment here and run `cargo +nightly fmt` manually without nix for https://github.com/oxalica/rust-overlay/issues/66#issuecomment-993816000 -#(cd parachain && SKIP_WASM_BUILD= cargo +nightly fmt --all) - +// checks that the cumulus submodule is in sync with our substrate dependencies check_duplicate_versions() { local duplicates=`grep -Ei "source = \"git.*$1" cumulus/Cargo.lock parachain/Cargo.lock | sed 's/\.git//g' | sort -u` local version_count=`echo "$duplicates" | awk -F':' '{for (i=2; i src/parachains/bridgehub.rs # Generate Rust bindings for contracts -forge bind --module --overwrite --bindings-path src/contracts --root ../core/packages/contracts +forge bind --module --overwrite \ + --select 'IGateway|WETH9' \ + --bindings-path src/contracts \ + --root ../contracts diff --git a/smoketest/src/parachains/mod.rs b/smoketest/src/parachains/mod.rs index c1eef7440607c..47f069a638259 100644 --- a/smoketest/src/parachains/mod.rs +++ b/smoketest/src/parachains/mod.rs @@ -1,2 +1,2 @@ - -pub mod bridgehub; +// TODO: implement smoke tests for Polkadot -> Ethereum +// pub mod bridgehub; diff --git a/smoketest/tests/create_token.rs b/smoketest/tests/register_token.rs similarity index 53% rename from smoketest/tests/create_token.rs rename to smoketest/tests/register_token.rs index 0873ac77e0ce1..2270a1c77da52 100644 --- a/smoketest/tests/create_token.rs +++ b/smoketest/tests/register_token.rs @@ -1,4 +1,4 @@ -use snowbridge_smoketest::contracts::{native_tokens, weth9}; +use snowbridge_smoketest::contracts::{i_gateway, weth9}; use std::{sync::Arc, time::Duration}; @@ -7,38 +7,40 @@ use ethers::{ middleware::SignerMiddleware, providers::{Http, Provider}, signers::{LocalWallet, Signer}, + utils::parse_units, + utils::rlp::Encodable, }; -// The deployment addresses of the following contracts are stable, unless we modify the order in +// The deployment addresses of the following contracts are stable in our E2E env, unless we modify the order in // contracts are deployed in DeployScript.sol. const ETHEREUM_API: &str = "http://localhost:8545"; const ETHEREUM_KEY: &str = "0x5e002a1af63fd31f1c25258f3082dc889762664cb8f218d86da85dff8b07b342"; -const NATIVE_TOKENS_CONTRACT: &str = "0x8cF6147918A5CBb672703F879f385036f8793a24"; -const WETH_CONTRACT: &str = "0x440eDFFA1352B13227e8eE646f3Ea37456deC701"; +const GATEWAY_PROXY_CONTRACT: &str = "0xEDa338E4dC46038493b885327842fD3E301CaB39"; +const WETH_CONTRACT: &str = "0x87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"; #[tokio::test] -async fn create_tokens() { +async fn register_token() { let provider = Provider::::try_from(ETHEREUM_API) .unwrap() .interval(Duration::from_millis(10u64)); - let wallet: LocalWallet = ETHEREUM_KEY .parse::() .unwrap() .with_chain_id(15u64); - - let client = SignerMiddleware::new(provider.clone(), wallet.clone()); + let client = SignerMiddleware::new(provider, wallet); let client = Arc::new(client); - let native_tokens_addr = NATIVE_TOKENS_CONTRACT.parse::
().unwrap(); - let native_tokens = native_tokens::NativeTokens::new(native_tokens_addr, client.clone()); + let gateway_addr = GATEWAY_PROXY_CONTRACT.parse::
().unwrap(); + let gateway = i_gateway::IGateway::new(gateway_addr, client.clone()); let weth_addr = WETH_CONTRACT.parse::
().unwrap(); let weth = weth9::WETH9::new(weth_addr, client.clone()); - let receipt = native_tokens - .create(weth.address()) - .value(1000) + let fee = parse_units(2, "ether").unwrap(); + + let receipt = gateway + .register_token(weth.address()) + .value(fee) .send() .await .unwrap() @@ -46,5 +48,13 @@ async fn create_tokens() { .unwrap() .unwrap(); + // Log for OutboundMessageAccepted + let outbound_message_accepted_log = receipt.logs.last().unwrap(); + // RLP-encode log and print it + println!( + "receipt: {:#?}", + hex::encode(outbound_message_accepted_log.rlp_bytes()) + ); + assert_eq!(receipt.status.unwrap().as_u64(), 1u64); } diff --git a/smoketest/tests/lock_tokens.rs b/smoketest/tests/send_token.rs similarity index 64% rename from smoketest/tests/lock_tokens.rs rename to smoketest/tests/send_token.rs index 9c27df05820df..4e5bdcf2ae95c 100644 --- a/smoketest/tests/lock_tokens.rs +++ b/smoketest/tests/send_token.rs @@ -1,5 +1,5 @@ use hex_literal::hex; -use snowbridge_smoketest::contracts::{native_tokens, weth9}; +use snowbridge_smoketest::contracts::{i_gateway, weth9}; use std::{sync::Arc, time::Duration}; use ethers::{ @@ -10,23 +10,19 @@ use ethers::{ utils::parse_units, }; -use codec::Encode; - -use xcm::v3::{MultiLocation, Junction, Junctions::X1}; - -// The deployment addresses of the following contracts are stable, unless we modify the order in +// The deployment addresses of the following contracts are stable in our E2E env, unless we modify the order in // contracts are deployed in DeployScript.sol. const ETHEREUM_API: &str = "http://localhost:8545"; const ETHEREUM_KEY: &str = "0x5e002a1af63fd31f1c25258f3082dc889762664cb8f218d86da85dff8b07b342"; -const TOKEN_VAULT_CONTRACT: &str = "0xB8EA8cB425d85536b158d661da1ef0895Bb92F1D"; -const NATIVE_TOKENS_CONTRACT: &str = "0x8cF6147918A5CBb672703F879f385036f8793a24"; -const WETH_CONTRACT: &str = "0x440eDFFA1352B13227e8eE646f3Ea37456deC701"; +const GATEWAY_PROXY_CONTRACT: &str = "0xEDa338E4dC46038493b885327842fD3E301CaB39"; +const WETH_CONTRACT: &str = "0x87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d"; // SS58: DE14BzQ1bDXWPKeLoAqdLAm1GpyAWaWF1knF74cEZeomTBM const FERDIE: [u8; 32] = hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"); +// TODO: test sendNativeToken #[tokio::test] -async fn test_lock_tokens() { +async fn send_tokens() { let provider = Provider::::try_from(ETHEREUM_API) .unwrap() .interval(Duration::from_millis(10u64)); @@ -39,16 +35,14 @@ async fn test_lock_tokens() { let client = SignerMiddleware::new(provider.clone(), wallet.clone()); let client = Arc::new(client); - let native_tokens_addr = NATIVE_TOKENS_CONTRACT.parse::
().unwrap(); - let native_tokens = native_tokens::NativeTokens::new(native_tokens_addr, client.clone()); - - let token_vault_addr = TOKEN_VAULT_CONTRACT.parse::
().unwrap(); + let gateway_addr = GATEWAY_PROXY_CONTRACT.parse::
().unwrap(); + let gateway = i_gateway::IGateway::new(gateway_addr, client.clone()); let weth_addr = WETH_CONTRACT.parse::
().unwrap(); let weth = weth9::WETH9::new(weth_addr, client.clone()); // Mint WETH tokens - let value = parse_units("10", "ether").unwrap(); + let value = parse_units("1", "ether").unwrap(); let receipt = weth .deposit() .value(value) @@ -61,7 +55,7 @@ async fn test_lock_tokens() { assert_eq!(receipt.status.unwrap().as_u64(), 1u64); // Approve token spend - weth.approve(token_vault_addr, value.into()) + weth.approve(gateway_addr, value.into()) .send() .await .unwrap() @@ -70,18 +64,10 @@ async fn test_lock_tokens() { .unwrap(); assert_eq!(receipt.status.unwrap().as_u64(), 1u64); - let recipient = MultiLocation { - parents: 0, - interior: X1(Junction::AccountId32{ - network: None, - id: FERDIE, - }) - }.encode(); - // Lock tokens into vault let value1: u128 = U256::from(value).low_u128(); - native_tokens - .lock(weth.address(), 0, recipient.into(), value1) + let receipt = gateway + .send_token(weth.address(), 1000.into(), FERDIE, value1) .value(1000) .send() .await diff --git a/core/.editorconfig b/web/.editorconfig similarity index 100% rename from core/.editorconfig rename to web/.editorconfig diff --git a/core/.gitignore b/web/.gitignore similarity index 100% rename from core/.gitignore rename to web/.gitignore diff --git a/core/.nvmrc b/web/.nvmrc similarity index 100% rename from core/.nvmrc rename to web/.nvmrc diff --git a/core/README.md b/web/README.md similarity index 100% rename from core/README.md rename to web/README.md diff --git a/core/init.sh b/web/init.sh similarity index 72% rename from core/init.sh rename to web/init.sh index dfd7f0633836d..1a024c6708b98 100755 --- a/core/init.sh +++ b/web/init.sh @@ -4,11 +4,10 @@ echo "Update submodules" (cd .. && (git submodule update --init --recursive||true)) echo "Install husky hook" -(cd .. && ./core/node_modules/.bin/husky install) +(cd .. && ./web/node_modules/.bin/husky install) echo "Installing sszgen" go install github.com/ferranbt/fastssz/sszgen@latest echo "Initialize foundry libraries" -(cd packages/contracts && forge install) - +(cd ../contracts && forge install) diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000000000..9b6fcc54b836c --- /dev/null +++ b/web/package.json @@ -0,0 +1,22 @@ +{ + "name": "@snowbridge/web", + "private": true, + "engines": { + "node": "v18.16.1", + "pnpm": "8.6.6" + }, + "scripts": { + "preinstall": "npx only-allow pnpm", + "build": "turbo run build", + "test": "turbo run test", + "lint": "turbo run lint", + "format": "turbo run format", + "size": "turbo run size", + "coverage": "turbo run coverage", + "remixd": "./node_modules/.bin/remixd" + }, + "devDependencies": { + "@remix-project/remixd": "^0.6.14", + "turbo": "^1.9.4" + } +} diff --git a/core/packages/api/.editorconfig b/web/packages/api/.editorconfig similarity index 100% rename from core/packages/api/.editorconfig rename to web/packages/api/.editorconfig diff --git a/core/packages/api/.eslintrc.json b/web/packages/api/.eslintrc.json similarity index 100% rename from core/packages/api/.eslintrc.json rename to web/packages/api/.eslintrc.json diff --git a/core/packages/api/.gitignore b/web/packages/api/.gitignore similarity index 100% rename from core/packages/api/.gitignore rename to web/packages/api/.gitignore diff --git a/core/packages/api/.prettierrc b/web/packages/api/.prettierrc similarity index 100% rename from core/packages/api/.prettierrc rename to web/packages/api/.prettierrc diff --git a/core/packages/api/README.md b/web/packages/api/README.md similarity index 100% rename from core/packages/api/README.md rename to web/packages/api/README.md diff --git a/core/packages/api/package.json b/web/packages/api/package.json similarity index 58% rename from core/packages/api/package.json rename to web/packages/api/package.json index f3f5b16dc410e..6159bb6db1d6a 100644 --- a/core/packages/api/package.json +++ b/web/packages/api/package.json @@ -6,11 +6,12 @@ "repository": { "type": "git", "url": "https://github.com/Snowfork/snowbridge.git", - "directory": "core/packages/api" + "directory": "web/packages/api" }, "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { + "build": "tsc", "lint": "eslint ." }, "devDependencies": { @@ -19,16 +20,20 @@ "@typescript-eslint/parser": "^5.42.0", "eslint": "^8.26.0", "eslint-config-prettier": "^8.5.0", - "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^7.1.5", "prettier": "^2.7.1", "ts-node": "^10.9.1", - "typescript": "^4.8.4" + "typescript": "^5.1.6", + "tsconfig-paths": "^4.2.0" }, "dependencies": { - "@polkadot/api": "10.7.1", - "@polkadot/types": "10.7.1", - "@snowbridge/contracts": "workspace:*", - "ethers": "^5.7.2" + "@polkadot/api": "^10.9.1", + "@polkadot/types": "^10.9.1", + "@snowbridge/contract-types": "workspace:*", + "@typechain/ethers-v5": "^11.1.1", + "ethers": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/providers": "^5.7.0", + "@ethersproject/units": "^5.7.0", + "@ethersproject/abi": "^5.7.0" } } diff --git a/core/packages/api/src/index.ts b/web/packages/api/src/index.ts similarity index 62% rename from core/packages/api/src/index.ts rename to web/packages/api/src/index.ts index c04fdc58c97da..37c464358bf00 100644 --- a/core/packages/api/src/index.ts +++ b/web/packages/api/src/index.ts @@ -1,16 +1,7 @@ -import "@polkadot/api-augment/polkadot" - -import { ethers } from "ethers" +// import "@polkadot/api-augment/polkadot" import { ApiPromise, WsProvider } from "@polkadot/api" -import { H160 } from "@polkadot/types/interfaces" -import { - DOTApp, - DOTApp__factory, - ETHApp, - ETHApp__factory, - ERC20App, - ERC20App__factory -} from "@snowbridge/contracts" +import { ethers } from "ethers" +import { IGateway, IGateway__factory } from "@snowbridge/contract-types" interface Config { ethereum: { @@ -22,9 +13,7 @@ interface Config { } interface AppContracts { - dotApp: DOTApp - ethApp: ETHApp - erc20App: ERC20App + gateway: IGateway } class Context { @@ -58,17 +47,13 @@ class PolkadotContext { const contextFactory = async (config: Config): Promise => { let ethApi = new ethers.providers.WebSocketProvider(config.ethereum.url) let polApi = await ApiPromise.create({ - provider: new WsProvider(config.polkadot.url) + provider: new WsProvider(config.polkadot.url), }) - let dotAppAddr = await polApi.query.dotApp.address() - let ethAppAddr = await polApi.query.ethApp.address() - let erc20AppAddr = await polApi.query.erc20App.address() + let gatewayAddr = process.env["GatewayProxyAddress"]! let appContracts: AppContracts = { - dotApp: DOTApp__factory.connect(dotAppAddr.toHex(), ethApi), - ethApp: ETHApp__factory.connect(ethAppAddr.toHex(), ethApi), - erc20App: ERC20App__factory.connect(erc20AppAddr.toHex(), ethApi) + gateway: IGateway__factory.connect(gatewayAddr, ethApi), } let ethCtx = new EthereumContext(ethApi, appContracts) diff --git a/core/packages/api/tsconfig.json b/web/packages/api/tsconfig.json similarity index 83% rename from core/packages/api/tsconfig.json rename to web/packages/api/tsconfig.json index b2d1b4e66264b..56a5474ebb6db 100644 --- a/core/packages/api/tsconfig.json +++ b/web/packages/api/tsconfig.json @@ -14,17 +14,13 @@ "baseUrl": ".", "rootDir": "src", "noEmitOnError": true, + "skipLibCheck": true, + "allowJs": true }, "ts-node": { "require": ["tsconfig-paths/register"] }, "exclude": ["node_modules", "dist"], - "include": [ - "src/**/*.ts", - ], - "references": [ - { - "path": "../contracts" - } - ] + "include": ["src/**/*.ts"], + "references": [] } diff --git a/web/packages/contract-types/.editorconfig b/web/packages/contract-types/.editorconfig new file mode 100644 index 0000000000000..49e9692f49a15 --- /dev/null +++ b/web/packages/contract-types/.editorconfig @@ -0,0 +1,4 @@ +[src/**.{ts,json,js}] +charset = utf-8 +indent_style = space +indent_size = 4 diff --git a/web/packages/contract-types/.gitignore b/web/packages/contract-types/.gitignore new file mode 100644 index 0000000000000..546d0e5d6ee79 --- /dev/null +++ b/web/packages/contract-types/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +src/ +tsconfig.tsbuildinfo diff --git a/web/packages/contract-types/README.md b/web/packages/contract-types/README.md new file mode 100644 index 0000000000000..ee54dc27af487 --- /dev/null +++ b/web/packages/contract-types/README.md @@ -0,0 +1 @@ +# contract-types diff --git a/web/packages/contract-types/package.json b/web/packages/contract-types/package.json new file mode 100644 index 0000000000000..c611ecea5bd9c --- /dev/null +++ b/web/packages/contract-types/package.json @@ -0,0 +1,31 @@ +{ + "name": "@snowbridge/contract-types", + "version": "1.0.0", + "description": "Snowbridge contract type bindings", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/Snowfork/snowbridge.git", + "directory": "web/packages/contract-types" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "typechain": "typechain --target ethers-v5 '../../../contracts/out/?(IGateway.sol|BeefyClient.sol)/!(*.abi).json' --out-dir src" + }, + "devDependencies": { + "@types/node": "^18.13.0", + "ts-node": "^10.9.1", + "typescript": "^5.1.6", + "typechain": "^8.3.1" + }, + "dependencies": { + "ethers": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/providers": "^5.7.0", + "@ethersproject/units": "^5.7.0", + "@ethersproject/abi": "^5.7.0", + "@typechain/ethers-v5": "^11.1.1" + } +} diff --git a/web/packages/contract-types/tsconfig.json b/web/packages/contract-types/tsconfig.json new file mode 100644 index 0000000000000..56a5474ebb6db --- /dev/null +++ b/web/packages/contract-types/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "composite": true, + "target": "es2021", + "module": "commonjs", + "strict": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "outDir": "dist", + "allowSyntheticDefaultImports": true, + "declaration": true, + "declarationMap": true, + "baseUrl": ".", + "rootDir": "src", + "noEmitOnError": true, + "skipLibCheck": true, + "allowJs": true + }, + "ts-node": { + "require": ["tsconfig-paths/register"] + }, + "exclude": ["node_modules", "dist"], + "include": ["src/**/*.ts"], + "references": [] +} diff --git a/web/packages/test-helpers/.editorconfig b/web/packages/test-helpers/.editorconfig new file mode 100644 index 0000000000000..49e9692f49a15 --- /dev/null +++ b/web/packages/test-helpers/.editorconfig @@ -0,0 +1,4 @@ +[src/**.{ts,json,js}] +charset = utf-8 +indent_style = space +indent_size = 4 diff --git a/core/packages/contracts/.eslintrc.json b/web/packages/test-helpers/.eslintrc.json similarity index 64% rename from core/packages/contracts/.eslintrc.json rename to web/packages/test-helpers/.eslintrc.json index 577dd8fa94cb2..87c35999c28a3 100644 --- a/core/packages/contracts/.eslintrc.json +++ b/web/packages/test-helpers/.eslintrc.json @@ -17,16 +17,5 @@ } ] }, - "ignorePatterns": [ - "dist", - "artifacts", - "build", - "contracts", - "src/**/*.ts", - "src/**/*.js", - "truffle-config.js", - "coverage", - "test/**/ffi*.js", - "scripts/generateContractInfo.js" - ] + "ignorePatterns": [] } diff --git a/web/packages/test-helpers/.gitignore b/web/packages/test-helpers/.gitignore new file mode 100644 index 0000000000000..f06235c460c2d --- /dev/null +++ b/web/packages/test-helpers/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/core/packages/contracts/.prettierrc b/web/packages/test-helpers/.prettierrc similarity index 100% rename from core/packages/contracts/.prettierrc rename to web/packages/test-helpers/.prettierrc diff --git a/web/packages/test-helpers/README.md b/web/packages/test-helpers/README.md new file mode 100644 index 0000000000000..4b1c976141e9a --- /dev/null +++ b/web/packages/test-helpers/README.md @@ -0,0 +1 @@ +# test-helpers diff --git a/web/packages/test-helpers/package.json b/web/packages/test-helpers/package.json new file mode 100644 index 0000000000000..944ed9635ca44 --- /dev/null +++ b/web/packages/test-helpers/package.json @@ -0,0 +1,53 @@ +{ + "name": "@snowbridge/test-helpers", + "version": "1.0.0", + "description": "Snowbridge test helpers", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/Snowfork/snowbridge.git", + "directory": "web/packages/test-helpers" + }, + "scripts": { + "build": "tsc", + "lint": "eslint src/*", + "generateBeefyCheckpoint": "npx ts-node src/generateBeefyCheckpoint.ts", + "generateContracts": "npx ts-node src/generateContractInfo.ts", + "generateBeefyValidatorSet": "npx ts-node src/generateBeefyTestFixture.ts GenerateInitialSet", + "generateBeefyFinalProof": "npx ts-node src/generateBeefyTestFixture.ts GenerateProofs" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^5.42.0", + "@typescript-eslint/parser": "^5.42.0", + "eslint": "^8.26.0", + "eslint-config-prettier": "^8.5.0", + "ts-node": "^10.9.1", + "typescript": "^5.1.6", + "tsconfig-paths": "^4.2.0" + }, + "dependencies": { + "bitfield": "^4.1.0", + "@ethersproject/abi": "^5.0.0", + "@polkadot/api": "^10.9.1", + "@polkadot/types": "^10.9.1", + "@typechain/ethers-v5": "^10.1.1", + "@types/keccak": "^3.0.1", + "@types/lodash": "^4.14.186", + "@types/node": "^18.13.0", + "@types/secp256k1": "^4.0.3", + "@types/seedrandom": "^3.0.2", + "@ethersproject/bytes": "^5.0.0", + "@ethersproject/providers": "^5.4.7", + "@ethersproject/units": "^5.4.7", + "ethers": "^5.7.2", + "ethereumjs-abi": "^0.6.8", + "ethereumjs-util": "^7.0.10", + "keccak": "^3.0.2", + "lodash": "^4.17.21", + "merkletreejs": "^0.2.18", + "rlp": "^2.2.6", + "secp256k1": "^4.0.2", + "seedrandom": "^3.0.5", + "@snowbridge/contract-types": "workspace:*" + } +} diff --git a/core/packages/contracts/scripts/configure-beefy.ts b/web/packages/test-helpers/src/generateBeefyCheckpoint.ts old mode 100644 new mode 100755 similarity index 67% rename from core/packages/contracts/scripts/configure-beefy.ts rename to web/packages/test-helpers/src/generateBeefyCheckpoint.ts index 3016aa6bb0959..8a0e108784cf4 --- a/core/packages/contracts/scripts/configure-beefy.ts +++ b/web/packages/test-helpers/src/generateBeefyCheckpoint.ts @@ -10,13 +10,15 @@ import type { import fs from "fs" import path from "path" -let endpoint = process.env.RELAYCHAIN_ENDPOINT || "ws://127.0.0.1:9944" -const beefyStartBlock = process.env.BEEFY_START_BLOCK ? parseInt(process.env.BEEFY_START_BLOCK) : 1 -const BeefyStateFile = - process.env.BEEFY_STATE_FILE || path.join(process.env.output_dir!, "beefy-state.json") - -async function configureBeefy() { - let api1 = await ApiPromise.create({ +async function generateBeefyCheckpoint() { + const endpoint = process.env.RELAYCHAIN_ENDPOINT || "ws://127.0.0.1:9944" + const beefyStartBlock = process.env.BEEFY_START_BLOCK + ? parseInt(process.env.BEEFY_START_BLOCK) + : 1 + const basedir = process.env.contract_dir || "../../../contracts" + const BeefyStateFile = path.join(basedir, "beefy-state.json") + + const api1 = await ApiPromise.create({ provider: new WsProvider(endpoint), }) @@ -33,12 +35,12 @@ async function configureBeefy() { }) }) - let blockHash = await api1.rpc.chain.getBlockHash(beefyStartBlock) + const blockHash = await api1.rpc.chain.getBlockHash(beefyStartBlock) - let api = await api1.at(blockHash) + const api = await api1.at(blockHash) - let validatorSetId = await api.query.beefy.validatorSetId() - let authorities = await api.query.beefy.authorities() + const validatorSetId = await api.query.beefy.validatorSetId() + const authorities = await api.query.beefy.authorities() let addrs = [] for (let i = 0; i < authorities.length; i++) { @@ -47,11 +49,12 @@ async function configureBeefy() { addrs.push(publicKeyHashed.slice(12)) } - let tree = createMerkleTree(addrs) + const tree = createMerkleTree(addrs) - let nextAuthorities = await api.query.mmrLeaf.beefyNextAuthorities() + const nextAuthorities = await api.query.mmrLeaf.beefyNextAuthorities() - let validatorSets = { + const beefyCheckpoint = { + startBlock: beefyStartBlock, current: { id: validatorSetId.toNumber(), root: tree.getHexRoot(), @@ -64,13 +67,10 @@ async function configureBeefy() { }, } - console.log("Configuring BeefyClient with initial BEEFY state") - console.log("Validator sets: ", validatorSets) + console.log("Configuring BeefyClient with initial BEEFY state", beefyCheckpoint) - fs.writeFileSync(BeefyStateFile, JSON.stringify({ validatorSets }, null, 2), "utf8") + fs.writeFileSync(BeefyStateFile, JSON.stringify(beefyCheckpoint, null, 2), "utf8") console.log("Beefy state writing to dest file: " + BeefyStateFile) - - return } function hasher(data: Buffer): Buffer { @@ -88,7 +88,7 @@ function createMerkleTree(leaves: Buffer[]) { // We recommend this pattern to be able to use async/await everywhere // and properly handle errors. -configureBeefy() +generateBeefyCheckpoint() .then(() => process.exit(0)) .catch((error) => { console.error(error) diff --git a/web/packages/test-helpers/src/generateBeefyTestFixture.ts b/web/packages/test-helpers/src/generateBeefyTestFixture.ts new file mode 100755 index 0000000000000..8f9e3398886ab --- /dev/null +++ b/web/packages/test-helpers/src/generateBeefyTestFixture.ts @@ -0,0 +1,85 @@ +import { ValidatorSet, createRandomSubset, readSetBits } from "./helpers" +import { BigNumber, ethers } from "ethers" +import type { BeefyClient } from "@snowbridge/contract-types" +import { accounts } from "./wallets" +import path from "path" +import fs from "fs" +const encoder = new ethers.utils.AbiCoder() + +const run = async () => { + const basedir = process.env.contract_dir || "../../../contracts" + const fixtureData = JSON.parse( + fs.readFileSync(path.join(basedir, "test/data/beefy-commitment.json"), "utf8") + ) + const BeefyValidatorSetFile = path.join(basedir, "test/data/beefy-validator-set.json") + const BeefyBitFieldFile = path.join(basedir, "test/data/beefy-final-bitfield.json") + const BeefyValidatorProofFile = path.join(basedir, "test/data/beefy-final-proof.json") + const command = process.argv[2] + const validatorSetID = fixtureData.params.id + const validatorSetSize = + process.env["FixedSet"] == "true" + ? accounts.length + : process.env["ValidatorSetSize"] + ? parseInt(process.env["ValidatorSetSize"]) + : 300 + const commitHash = fixtureData.commitmentHash + let validatorSet: ValidatorSet + if (process.env["FixedSet"] == "true") { + validatorSet = new ValidatorSet( + validatorSetID, + validatorSetSize, + accounts.map((account) => account.privateKey) + ) + } else { + validatorSet = new ValidatorSet(validatorSetID, validatorSetSize) + } + + if (command == "GenerateInitialSet") { + const absentSubsetSize = Math.floor((validatorSetSize - 1) / 3) + const subsetSize = validatorSetSize - absentSubsetSize + const randomSet = createRandomSubset(validatorSetSize, subsetSize) + const participants = randomSet.participants + const absentees = randomSet.absentees + + const testFixture = { + validatorSetSize, + participants, + absentees, + validatorRoot: validatorSet.root, + } + console.log("Validator Set", testFixture) + fs.writeFileSync(BeefyValidatorSetFile, JSON.stringify(testFixture, null, 2), "utf8") + console.log("Beefy fixture writing to dest file: " + BeefyValidatorSetFile) + } else if (command == "GenerateProofs") { + const testFixture = JSON.parse(fs.readFileSync(BeefyBitFieldFile, "utf8")) + const bitField = encoder.decode(["uint256[]"], testFixture.final.finalBitFieldRaw)[0] + console.log(bitField) + let finalBitfield: BigNumber[] = [] + for (let i = 0; i < bitField.length; i++) { + finalBitfield.push(bitField[i]) + } + const finalValidatorsProof: BeefyClient.ValidatorProofStruct[] = readSetBits( + finalBitfield + ).map((i) => validatorSet.createSignatureProof(i, commitHash)) + console.log("Final Validator proofs:", finalValidatorsProof) + const finalValidatorsProofRaw = encoder.encode( + [ + "tuple(uint8 v, bytes32 r, bytes32 s, uint256 index,address account,bytes32[] proof)[]", + ], + [finalValidatorsProof] + ) + fs.writeFileSync( + BeefyValidatorProofFile, + JSON.stringify({ finalValidatorsProof, finalValidatorsProofRaw }, null, 2), + "utf8" + ) + console.log("Beefy fixture writing to dest file: " + BeefyValidatorProofFile) + } +} + +run() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) diff --git a/web/packages/test-helpers/src/generateContractInfo.ts b/web/packages/test-helpers/src/generateContractInfo.ts new file mode 100644 index 0000000000000..0a25743cf336b --- /dev/null +++ b/web/packages/test-helpers/src/generateContractInfo.ts @@ -0,0 +1,49 @@ +import fs from "fs" +import path from "path" + +const run = async () => { + const NetworkId = process.env.ETH_NETWORK_ID || 15 + const basedir = process.env.contract_dir || "../contracts" + const DeployInfoFile = path.join( + basedir, + `./broadcast/DeployScript.sol/${NetworkId}/run-latest.json` + ) + const BuildInfoDir = path.join(basedir, "./out") + const DestFile = + process.argv.length >= 3 ? process.argv[2] : process.env["output_dir"] + "/contracts.json" + type Contract = { + [key: string]: ContractInfo + } + let contracts: Contract = {} + const deploymentInfo = JSON.parse(fs.readFileSync(DeployInfoFile, "utf8")) + type ContractInfo = { + abi?: object + address?: string + } + for (let transaction of deploymentInfo.transactions) { + if (transaction.transactionType === "CREATE") { + let contractName: string = transaction.contractName + if (contractName) { + let contractInfo: ContractInfo = { address: transaction.contractAddress } + let contractBuildingInfo = JSON.parse( + fs.readFileSync( + path.join(BuildInfoDir, contractName + ".sol", contractName + ".json"), + "utf8" + ) + ) + contractInfo.abi = contractBuildingInfo.abi + contracts[contractName] = contractInfo + } + } + } + fs.writeFileSync(DestFile, JSON.stringify({ contracts }, null, 2), "utf8") +} + +run() + .then(() => { + console.log("Contract File generated successfully") + process.exit(0) + }) + .catch((err) => { + console.error(err) + }) diff --git a/core/packages/contracts/scripts/helpers.ts b/web/packages/test-helpers/src/helpers.ts similarity index 91% rename from core/packages/contracts/scripts/helpers.ts rename to web/packages/test-helpers/src/helpers.ts index 69355595b5707..940366645d349 100644 --- a/core/packages/contracts/scripts/helpers.ts +++ b/web/packages/test-helpers/src/helpers.ts @@ -7,8 +7,7 @@ import _ from "lodash" import secp256k1 from "secp256k1" import seedrandom from "seedrandom" import { keccak256, entropyToMnemonic } from "ethers/lib/utils" - -import type { BeefyClient } from "../types/BeefyClient" +import type { BeefyClient } from "@snowbridge/contract-types" let readSetBits = (bitfield: ethers.BigNumber[]): number[] => { let bits = bitfield @@ -101,9 +100,12 @@ class ValidatorSet { function createRandomSubset(population: number, size: number) { seedrandom("test", { global: true }) - return _.runInContext() - .sampleSize(Array.from(Array(population).keys()), size) + const all = Array.from(Array(population).keys()) + const participants = _.runInContext() + .sampleSize(all, size) .sort((a, b) => a - b) + const absentees = all.filter((o) => !participants.includes(o)) + return { participants, absentees } } export { encodeLog, createRandomSubset, ValidatorSet, readSetBits } diff --git a/core/packages/contracts/scripts/wallets.ts b/web/packages/test-helpers/src/wallets.ts similarity index 100% rename from core/packages/contracts/scripts/wallets.ts rename to web/packages/test-helpers/src/wallets.ts diff --git a/core/packages/contracts/tsconfig.json b/web/packages/test-helpers/tsconfig.json similarity index 81% rename from core/packages/contracts/tsconfig.json rename to web/packages/test-helpers/tsconfig.json index 04f916d024536..ab173c440b507 100644 --- a/core/packages/contracts/tsconfig.json +++ b/web/packages/test-helpers/tsconfig.json @@ -13,15 +13,17 @@ "allowSyntheticDefaultImports": true, "declaration": true, "declarationMap": true, - "skipLibCheck": false, "baseUrl": ".", "noEmitOnError": true, - "sourceMap": true + "sourceMap": true, + "skipLibCheck": true, + "allowJs": true }, "ts-node": { "require": ["tsconfig-paths/register"] }, + "exclude": ["node_modules", "dist"], "include": [ - "types/**/*.ts", + "src/**/*.ts", ] } diff --git a/core/packages/test/.envrc-example b/web/packages/test/.envrc-example similarity index 90% rename from core/packages/test/.envrc-example rename to web/packages/test/.envrc-example index a5918d1752d3f..68da539ce7c86 100644 --- a/core/packages/test/.envrc-example +++ b/web/packages/test/.envrc-example @@ -9,7 +9,7 @@ source_up_if_exists # export BEEFY_START_BLOCK= # Start block to configure beefy client, default value: 1 # export RELAYCHAIN_ENDPOINT= # Relaychain endpoint, default value: ws://localhost:9944 # export PARACHAIN_RUNTIME= # Runtime type of parachain should be one of snowbase|snowblink|snowbridge -# export BRIDGEHUB_PALLETS_OWNER= # Pubkey of bridge owner which can be used to halt/resume the bridge pallets +# export BRIDGEHUB_PALLETS_OWNER= # Pubkey of bridge owner that can halt/resume the bridge pallets, default value: 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (Alice test account) ## Eth config for production diff --git a/core/packages/test/.gitignore b/web/packages/test/.gitignore similarity index 100% rename from core/packages/test/.gitignore rename to web/packages/test/.gitignore diff --git a/core/packages/test/README.md b/web/packages/test/README.md similarity index 100% rename from core/packages/test/README.md rename to web/packages/test/README.md diff --git a/core/packages/test/config/beacon-relay.json b/web/packages/test/config/beacon-relay.json similarity index 100% rename from core/packages/test/config/beacon-relay.json rename to web/packages/test/config/beacon-relay.json diff --git a/core/packages/test/config/beefy-relay.json b/web/packages/test/config/beefy-relay.json similarity index 100% rename from core/packages/test/config/beefy-relay.json rename to web/packages/test/config/beefy-relay.json diff --git a/core/packages/test/config/dev-example-ethereum-keys b/web/packages/test/config/dev-example-ethereum-keys similarity index 100% rename from core/packages/test/config/dev-example-ethereum-keys rename to web/packages/test/config/dev-example-ethereum-keys diff --git a/core/packages/test/config/dev-example-key0.prv b/web/packages/test/config/dev-example-key0.prv similarity index 100% rename from core/packages/test/config/dev-example-key0.prv rename to web/packages/test/config/dev-example-key0.prv diff --git a/core/packages/test/config/dev-example-key1.prv b/web/packages/test/config/dev-example-key1.prv similarity index 100% rename from core/packages/test/config/dev-example-key1.prv rename to web/packages/test/config/dev-example-key1.prv diff --git a/core/packages/test/config/execution-relay.json b/web/packages/test/config/execution-relay.json similarity index 84% rename from core/packages/test/config/execution-relay.json rename to web/packages/test/config/execution-relay.json index f7a0c43117fea..3422e5cee0f5c 100644 --- a/core/packages/test/config/execution-relay.json +++ b/web/packages/test/config/execution-relay.json @@ -4,9 +4,9 @@ "endpoint": "ws://127.0.0.1:8546" }, "contracts": { - "OutboundQueue": null + "Gateway": null }, - "lane-id": 1000 + "channel-id": 1000 }, "sink": { "parachain": { diff --git a/core/packages/test/config/genesis.json b/web/packages/test/config/genesis.json similarity index 97% rename from core/packages/test/config/genesis.json rename to web/packages/test/config/genesis.json index 9d7431a0988e0..c672a786a7c3a 100644 --- a/core/packages/test/config/genesis.json +++ b/web/packages/test/config/genesis.json @@ -21,7 +21,7 @@ "gasLimit": "80000000", "alloc": { "90A987B944Cb1dCcE5564e5FDeCD7a54D3de27Fe": { - "balance": "100000000000000000000" + "balance": "10000000000000000000000" }, "Be68fC2d8249eb60bfCf0e71D5A0d2F2e292c4eD": { "balance": "100000000000000000000" diff --git a/core/packages/test/config/jwtsecret b/web/packages/test/config/jwtsecret similarity index 100% rename from core/packages/test/config/jwtsecret rename to web/packages/test/config/jwtsecret diff --git a/core/packages/test/config/launch-config.toml b/web/packages/test/config/launch-config.toml similarity index 100% rename from core/packages/test/config/launch-config.toml rename to web/packages/test/config/launch-config.toml diff --git a/core/packages/test/config/parachain-relay.json b/web/packages/test/config/parachain-relay.json similarity index 86% rename from core/packages/test/config/parachain-relay.json rename to web/packages/test/config/parachain-relay.json index 71acb81de9d93..2da5c5be37626 100644 --- a/core/packages/test/config/parachain-relay.json +++ b/web/packages/test/config/parachain-relay.json @@ -11,10 +11,10 @@ }, "contracts": { "BeefyClient": null, - "InboundQueue": null + "Gateway": null }, "beefy-activation-block": 0, - "lane-id": 0 + "channel-id": 0 }, "sink": { "ethereum": { @@ -22,7 +22,7 @@ "gas-limit": null }, "contracts": { - "InboundQueue": null + "Gateway": null } } } diff --git a/core/packages/test/docs/burn-polkaeth.jpeg b/web/packages/test/docs/burn-polkaeth.jpeg similarity index 100% rename from core/packages/test/docs/burn-polkaeth.jpeg rename to web/packages/test/docs/burn-polkaeth.jpeg diff --git a/core/packages/test/docs/query-balance.jpeg b/web/packages/test/docs/query-balance.jpeg similarity index 100% rename from core/packages/test/docs/query-balance.jpeg rename to web/packages/test/docs/query-balance.jpeg diff --git a/core/packages/test/package.json b/web/packages/test/package.json similarity index 83% rename from core/packages/test/package.json rename to web/packages/test/package.json index ff7684262cc5c..4f92dec59f8ca 100644 --- a/core/packages/test/package.json +++ b/web/packages/test/package.json @@ -6,11 +6,7 @@ "repository": { "type": "git", "url": "https://github.com/Snowfork/snowbridge.git", - "directory": "core/packages/test" - }, - "scripts": { - "test:integration": "mocha --timeout 600000 --exit", - "test:bootstrap": "mocha --timeout 600000 --parallel --grep Bootstrap --exit" + "directory": "web/packages/test" }, "devDependencies": { "@chainsafe/lodestar": "1.8.0", diff --git a/core/packages/test/scripts/build-binary.sh b/web/packages/test/scripts/build-binary.sh similarity index 100% rename from core/packages/test/scripts/build-binary.sh rename to web/packages/test/scripts/build-binary.sh diff --git a/core/packages/test/scripts/configure-bridgehub.sh b/web/packages/test/scripts/configure-bridgehub.sh similarity index 94% rename from core/packages/test/scripts/configure-bridgehub.sh rename to web/packages/test/scripts/configure-bridgehub.sh index 47e679f351062..6c7e0e2206ff3 100755 --- a/core/packages/test/scripts/configure-bridgehub.sh +++ b/web/packages/test/scripts/configure-bridgehub.sh @@ -16,7 +16,8 @@ config_inbound_queue() { local pallet="30" local callindex="01" - local payload="0x$pallet$callindex$(address_for OutboundQueue | cut -c3-)" + local payload="0x$pallet$callindex$(address_for GatewayProxy | tr "[:upper:]" "[:lower:]" | cut -c3-)" + send_governance_transact_from_relaychain $bridgehub_para_id "$payload" } @@ -62,7 +63,7 @@ fund_accounts() transfer_balance $relaychain_ws_url "//Charlie" 1013 1000000000000000 $statemine_sovereign_account transfer_balance $relaychain_ws_url "//Charlie" 1013 1000000000000000 $beacon_relayer_pub_key transfer_balance $relaychain_ws_url "//Charlie" 1013 1000000000000000 $execution_relayer_pub_key - transfer_balance $relaychain_ws_url "//Charlie" 1000 1000000000000000 $registry_contract_sovereign_account + transfer_balance $relaychain_ws_url "//Charlie" 1000 1000000000000000 $gateway_contract_sovereign_account } configure_bridgehub() diff --git a/core/packages/test/scripts/deploy-contracts.sh b/web/packages/test/scripts/deploy-contracts.sh similarity index 88% rename from core/packages/test/scripts/deploy-contracts.sh rename to web/packages/test/scripts/deploy-contracts.sh index 14c71af469553..5ac60bf26eb81 100755 --- a/core/packages/test/scripts/deploy-contracts.sh +++ b/web/packages/test/scripts/deploy-contracts.sh @@ -21,8 +21,12 @@ deploy_contracts() -vvv \ src/DeployScript.sol:DeployScript fi - node scripts/generateContractInfo.js "$output_dir/contracts.json" popd + + pushd "$test_helpers_dir" + pnpm generateContracts "$output_dir/contracts.json" + popd + echo "Exported contract artifacts: $output_dir/contracts.json" } diff --git a/core/packages/test/scripts/deploy-ethereum.sh b/web/packages/test/scripts/deploy-ethereum.sh similarity index 85% rename from core/packages/test/scripts/deploy-ethereum.sh rename to web/packages/test/scripts/deploy-ethereum.sh index df62251810581..1ce451e7681a3 100755 --- a/core/packages/test/scripts/deploy-ethereum.sh +++ b/web/packages/test/scripts/deploy-ethereum.sh @@ -67,17 +67,6 @@ start_lodestar() { fi } -hack_beacon_client() -{ - echo "Hack lodestar for faster slot time" - local preset_minimal_config_file="$core_dir/node_modules/.pnpm/@lodestar+config@$lodestar_version/node_modules/@lodestar/config/lib/chainConfig/presets/minimal.js" - if [[ "$(uname)" == "Darwin" && -z "${IN_NIX_SHELL:-}" ]]; then - gsed -i "s/SECONDS_PER_SLOT: 6/SECONDS_PER_SLOT: 1/g" $preset_minimal_config_file - else - sed -i "s/SECONDS_PER_SLOT: 6/SECONDS_PER_SLOT: 1/g" $preset_minimal_config_file - fi -} - deploy_local() { # 1. deploy execution client @@ -87,10 +76,6 @@ deploy_local() echo "Waiting for geth API to be ready" sleep 3 - if [ "$eth_fast_mode" == "true" ]; then - hack_beacon_client - fi - # 2. deploy consensus client echo "Starting beacon node" start_lodestar @@ -108,4 +93,3 @@ if [ -z "${from_start_services:-}" ]; then echo "ethereum local nodes started!" wait fi - diff --git a/core/packages/test/scripts/deploy-polkadot.sh b/web/packages/test/scripts/deploy-polkadot.sh similarity index 100% rename from core/packages/test/scripts/deploy-polkadot.sh rename to web/packages/test/scripts/deploy-polkadot.sh diff --git a/core/packages/test/scripts/fetch-beacon-data.sh b/web/packages/test/scripts/fetch-beacon-data.sh similarity index 100% rename from core/packages/test/scripts/fetch-beacon-data.sh rename to web/packages/test/scripts/fetch-beacon-data.sh diff --git a/web/packages/test/scripts/generate-beefy-checkpoint.sh b/web/packages/test/scripts/generate-beefy-checkpoint.sh new file mode 100755 index 0000000000000..917d2bc5ab771 --- /dev/null +++ b/web/packages/test/scripts/generate-beefy-checkpoint.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -eu + +source scripts/set-env.sh + +generate_beefy_checkpoint() +{ + pushd "$test_helpers_dir" + pnpm generateBeefyCheckpoint + popd +} + +if [ -z "${from_start_services:-}" ]; then + echo "generate beefy checkpoint!" + generate_beefy_checkpoint + wait +fi diff --git a/core/packages/test/scripts/helpers/make-xcm-transfer.ts b/web/packages/test/scripts/helpers/make-xcm-transfer.ts similarity index 100% rename from core/packages/test/scripts/helpers/make-xcm-transfer.ts rename to web/packages/test/scripts/helpers/make-xcm-transfer.ts diff --git a/core/packages/test/scripts/helpers/overrideParachainSpec.js b/web/packages/test/scripts/helpers/overrideParachainSpec.js similarity index 100% rename from core/packages/test/scripts/helpers/overrideParachainSpec.js rename to web/packages/test/scripts/helpers/overrideParachainSpec.js diff --git a/core/packages/test/scripts/helpers/poll-ethereum-events.ts b/web/packages/test/scripts/helpers/poll-ethereum-events.ts similarity index 100% rename from core/packages/test/scripts/helpers/poll-ethereum-events.ts rename to web/packages/test/scripts/helpers/poll-ethereum-events.ts diff --git a/core/packages/test/scripts/helpers/subscribeBeefyJustifications.js b/web/packages/test/scripts/helpers/subscribeBeefyJustifications.js similarity index 100% rename from core/packages/test/scripts/helpers/subscribeBeefyJustifications.js rename to web/packages/test/scripts/helpers/subscribeBeefyJustifications.js diff --git a/core/packages/test/scripts/helpers/transformEthHeader.js b/web/packages/test/scripts/helpers/transformEthHeader.js similarity index 100% rename from core/packages/test/scripts/helpers/transformEthHeader.js rename to web/packages/test/scripts/helpers/transformEthHeader.js diff --git a/core/packages/test/scripts/set-env.sh b/web/packages/test/scripts/set-env.sh similarity index 88% rename from core/packages/test/scripts/set-env.sh rename to web/packages/test/scripts/set-env.sh index 7a3c15480c13e..e627ff4b598ff 100755 --- a/core/packages/test/scripts/set-env.sh +++ b/web/packages/test/scripts/set-env.sh @@ -6,11 +6,12 @@ relaychain_bin="${POLKADOT_BIN:-$relaychain_dir/bin/polkadot}" cumulus_version="${CUMULUS_VER:-snowbridge}" cumulus_dir="$root_dir/parachain/.cargo/$cumulus_version" cumulus_bin="${CUMULUS_BIN:-$cumulus_dir/bin/polkadot-parachain}" -core_dir="$root_dir/core" +web_dir="$root_dir/web" lodestar_version="${LODESTAR_VER:-1.8.0}" geth_version="${GETH_VER:-v1.12.0}" geth_dir="$root_dir/../go-ethereum/$geth_version" -contract_dir="$core_dir/packages/contracts" +export contract_dir="$root_dir/contracts" +test_helpers_dir="$web_dir/packages/test-helpers" relay_dir="$root_dir/relayer" relay_bin="$relay_dir/build/snowbridge-relay" export output_dir="${OUTPUT_DIR:-/tmp/snowbridge}" @@ -28,9 +29,6 @@ eth_chain_id="${ETH_NETWORK_ID:-15}" eth_fast_mode="${ETH_FAST_MODE:-false}" etherscan_api_key="${ETHERSCAN_API_KEY:-}" -beefy_state_file="${BEEFY_STATE_FILE:-$output_dir/beefy-state.json}" -beefy_start_block="${BEEFY_START_BLOCK:-1}" - parachain_relay_eth_key="${PARACHAIN_RELAY_ETH_KEY:-0x8013383de6e5a891e7754ae1ef5a21e7661f1fe67cd47ca8ebf4acd6de66879a}" beefy_relay_eth_key="${BEEFY_RELAY_ETH_KEY:-0x935b65c833ced92c43ef9de6bff30703d941bd92a2637cb00cfad389f5862109}" @@ -65,8 +63,8 @@ statemine_sovereign_account="${STATEMINE_SOVEREIGN_ACCOUNT:-0x70617261e803000000 beacon_relayer_pub_key="${BEACON_RELAYER_PUB_KEY:-0xc46e141b5083721ad5f5056ba1cded69dce4a65f027ed3362357605b1687986a}" # Execution relay account (//ExecutionRelay 5CFNWKMFPsw5Cs2Teo6Pvg7rWyjKiFfqPZs8U4MZXzMYFwXL in testnet) execution_relayer_pub_key="${EXECUTION_RELAYER_PUB_KEY:-0x08228efd065c58a043da95c8bf177659fc587643e71e7ed1534666177730196f}" -# Registry contract account (5EBBfBLm4uV4JMXXcKvZrPVmP9VyER9YSCgGdMUw5wBXnqag in testnet) -registry_contract_sovereign_account="${REGISTRY_CONTRACT_SOVEREIGN_ACCOUNT:-0x5d6987649e0dac78ddf852eb0f1b1d1bf2be9623d81cb16c17cfa145948bb6dc}" +# Gateway contract account (H8VBFC4LG91ByxMG6GwsCcAacjitnzGmGbqnvSEQFBywJEL in testnet) +gateway_contract_sovereign_account="${GATEWAY_CONTRACT_SOVEREIGN_ACCOUNT:-0xc9794dd8013efb2ad83f668845c62b373c16ad33971745731408058e4d0c6ff5}" # Config for deploying contracts @@ -81,20 +79,22 @@ export PRIVATE_KEY="${DEPLOYER_ETH_KEY:-0x4e9444a6efd6d42725a250b650a781da2737ea export RANDAO_COMMIT_DELAY="${ETH_RANDAO_DELAY:-3}" export RANDAO_COMMIT_EXP="${ETH_RANDAO_EXP:-3}" -## ParachainClient export BRIDGE_HUB_PARAID=$bridgehub_para_id +# TODO: update placeholder value +export BRIDGE_HUB_AGENT_ID="0x05f0ced792884ed09997292bd95f8d0d1094bb3bded91ec3f2f08531624037d6" -## OutboundChannel -export RELAYER_FEE=1 +export ASSET_HUB_PARAID=$statemine_para_id +# TODO: update placeholder value +export ASSET_HUB_AGENT_ID="0x72456f48efed08af20e5b317abf8648ac66e86bb90a411d9b0b713f7364b75b4" -## InboundChannel -export RELAYER_REWARD=1 +export DEFAULT_FEE=1 +export DEFAULT_REWARD=1 -## NativeTokens -export ASSET_HUB_PARAID=$statemine_para_id -export CREATE_TOKEN_FEE=1 export CREATE_CALL_INDEX="0x3500" -export SET_METADATA_CALL_INDEX="0x3511" +export DISPATCH_GAS=500000 + +export REGISTER_NATIVE_TOKEN_FEE=0 +export SEND_NATIVE_TOKEN_FEE=0 ## Vault export BRIDGE_HUB_INITIAL_DEPOSIT=1000 diff --git a/core/packages/test/scripts/start-goerli.sh b/web/packages/test/scripts/start-goerli.sh similarity index 100% rename from core/packages/test/scripts/start-goerli.sh rename to web/packages/test/scripts/start-goerli.sh diff --git a/core/packages/test/scripts/start-relayer.sh b/web/packages/test/scripts/start-relayer.sh similarity index 88% rename from core/packages/test/scripts/start-relayer.sh rename to web/packages/test/scripts/start-relayer.sh index 960c352f466c0..6f8bcb0255a5d 100755 --- a/core/packages/test/scripts/start-relayer.sh +++ b/web/packages/test/scripts/start-relayer.sh @@ -19,37 +19,37 @@ config_relayer(){ # Configure parachain relay (bridge hub) jq \ - --arg k1 "$(address_for InboundQueue)" \ + --arg k1 "$(address_for GatewayProxy)" \ --arg k2 "$(address_for BeefyClient)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ - --arg laneID $BRIDGE_HUB_PARAID \ + --arg channelID $BRIDGE_HUB_PARAID \ --arg eth_gas_limit $eth_gas_limit \ ' - .source.contracts.InboundQueue = $k1 + .source.contracts.Gateway = $k1 | .source.contracts.BeefyClient = $k2 - | .sink.contracts.InboundQueue = $k1 + | .sink.contracts.Gateway = $k1 | .source.ethereum.endpoint = $eth_endpoint_ws | .sink.ethereum.endpoint = $eth_endpoint_ws | .sink.ethereum."gas-limit" = $eth_gas_limit - | .source."lane-id" = $laneID + | .source."channel-id" = $channelID ' \ config/parachain-relay.json > $output_dir/parachain-relay-bridge-hub.json # Configure parachain relay (asset hub) jq \ - --arg k1 "$(address_for InboundQueue)" \ + --arg k1 "$(address_for GatewayProxy)" \ --arg k2 "$(address_for BeefyClient)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ - --arg laneID $ASSET_HUB_PARAID \ + --arg channelID $ASSET_HUB_PARAID \ --arg eth_gas_limit $eth_gas_limit \ ' - .source.contracts.InboundQueue = $k1 + .source.contracts.Gateway = $k1 | .source.contracts.BeefyClient = $k2 - | .sink.contracts.InboundQueue = $k1 + | .sink.contracts.Gateway = $k1 | .source.ethereum.endpoint = $eth_endpoint_ws | .sink.ethereum.endpoint = $eth_endpoint_ws | .sink.ethereum."gas-limit" = $eth_gas_limit - | .source."lane-id" = $laneID + | .source."channel-id" = $channelID ' \ config/parachain-relay.json > $output_dir/parachain-relay-asset-hub.json @@ -66,12 +66,12 @@ config_relayer(){ # Configure execution relay jq \ --arg eth_endpoint_ws $eth_endpoint_ws \ - --arg k1 "$(address_for OutboundQueue)" \ - --arg laneID $ASSET_HUB_PARAID \ + --arg k1 "$(address_for GatewayProxy)" \ + --arg channelID $ASSET_HUB_PARAID \ ' .source.ethereum.endpoint = $eth_endpoint_ws - | .source.contracts.OutboundQueue = $k1 - | .source."lane-id" = $laneID + | .source.contracts.Gateway = $k1 + | .source."channel-id" = $channelID ' \ config/execution-relay.json > $output_dir/execution-relay.json } diff --git a/core/packages/test/scripts/start-services.sh b/web/packages/test/scripts/start-services.sh similarity index 83% rename from core/packages/test/scripts/start-services.sh rename to web/packages/test/scripts/start-services.sh index 5c9a8cf0e52a0..b7f88bf96b40b 100755 --- a/core/packages/test/scripts/start-services.sh +++ b/web/packages/test/scripts/start-services.sh @@ -30,24 +30,20 @@ else deploy_goerli fi -# 3. deploy contracts -echo "Deploying ethereum contracts" -source scripts/deploy-contracts.sh -deploy_contracts & - -# 4. start polkadot +# 3. start polkadot echo "Starting polkadot nodes" source scripts/deploy-polkadot.sh deploy_polkadot -# wait for contract deployed -echo "Waiting contract deployed" -wait_contract_deployed +# 4. generate beefy checkpoint +echo "Generate beefy checkpoint" +source scripts/generate-beefy-checkpoint.sh +generate_beefy_checkpoint -# 5. config beefy client -echo "Config beefy client" -source scripts/configure-beefy.sh -configure_beefy +# 5. deploy contracts +echo "Deploying ethereum contracts" +source scripts/deploy-contracts.sh +deploy_contracts # 6. config bridgehub echo "Config bridgehub" diff --git a/core/packages/test/scripts/wait-for-it.sh b/web/packages/test/scripts/wait-for-it.sh similarity index 100% rename from core/packages/test/scripts/wait-for-it.sh rename to web/packages/test/scripts/wait-for-it.sh diff --git a/core/packages/test/scripts/xcm-helper.sh b/web/packages/test/scripts/xcm-helper.sh similarity index 92% rename from core/packages/test/scripts/xcm-helper.sh rename to web/packages/test/scripts/xcm-helper.sh index 55800ffa637f2..4062e89d9b5cf 100644 --- a/core/packages/test/scripts/xcm-helper.sh +++ b/web/packages/test/scripts/xcm-helper.sh @@ -6,14 +6,8 @@ source scripts/set-env.sh send_governance_transact_from_relaychain() { local para_id=$1 local hex_encoded_data=$2 - local require_weight_at_most_ref_time=$(echo "$3") - local require_weight_at_most_proof_size=$(echo "$4") - if [ -z "${require_weight_at_most_ref_time}" ]; then - require_weight_at_most_ref_time=200000000 - fi - if [ -z "${require_weight_at_most_proof_size}" ]; then - require_weight_at_most_proof_size=12000 - fi + local require_weight_at_most_ref_time=${3:-200000000} + local require_weight_at_most_proof_size=${4:-12000} echo " calling send_governance_transact:" echo " relay_url: ${relaychain_ws_url}" echo " relay_chain_seed: ${relaychain_sudo_seed}" diff --git a/core/packages/test/src/.gitkeep b/web/packages/test/src/.gitkeep similarity index 100% rename from core/packages/test/src/.gitkeep rename to web/packages/test/src/.gitkeep diff --git a/core/packages/test/tsconfig.json b/web/packages/test/tsconfig.json similarity index 100% rename from core/packages/test/tsconfig.json rename to web/packages/test/tsconfig.json diff --git a/core/pnpm-lock.yaml b/web/pnpm-lock.yaml similarity index 82% rename from core/pnpm-lock.yaml rename to web/pnpm-lock.yaml index 3191e76e56d40..949db19a282d4 100644 --- a/core/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -1,5 +1,9 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + importers: .: @@ -7,26 +11,38 @@ importers: '@remix-project/remixd': specifier: ^0.6.14 version: 0.6.14 - husky: - specifier: ^8.0.3 - version: 8.0.3 turbo: specifier: ^1.9.4 version: 1.9.4 packages/api: dependencies: + '@ethersproject/abi': + specifier: ^5.7.0 + version: 5.7.0 + '@ethersproject/bytes': + specifier: ^5.7.0 + version: 5.7.0 + '@ethersproject/providers': + specifier: ^5.7.0 + version: 5.7.2 + '@ethersproject/units': + specifier: ^5.7.0 + version: 5.7.0 '@polkadot/api': - specifier: 10.7.1 - version: 10.7.1 + specifier: ^10.9.1 + version: 10.9.1 '@polkadot/types': - specifier: 10.7.1 - version: 10.7.1 - '@snowbridge/contracts': + specifier: ^10.9.1 + version: 10.9.1 + '@snowbridge/contract-types': specifier: workspace:* - version: link:../contracts + version: link:../contract-types + '@typechain/ethers-v5': + specifier: ^11.1.1 + version: 11.1.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6) ethers: - specifier: ^5.7.2 + specifier: ^5.7.0 version: 5.7.2 devDependencies: '@types/node': @@ -34,179 +50,62 @@ importers: version: 18.16.8 '@typescript-eslint/eslint-plugin': specifier: ^5.42.0 - version: 5.42.0(@typescript-eslint/parser@5.42.0)(eslint@8.26.0)(typescript@4.9.5) + version: 5.42.0(@typescript-eslint/parser@5.42.0)(eslint@8.26.0)(typescript@5.1.6) '@typescript-eslint/parser': specifier: ^5.42.0 - version: 5.42.0(eslint@8.26.0)(typescript@4.9.5) + version: 5.42.0(eslint@8.26.0)(typescript@5.1.6) eslint: specifier: ^8.26.0 version: 8.26.0 eslint-config-prettier: specifier: ^8.5.0 version: 8.5.0(eslint@8.26.0) - ethereumjs-abi: - specifier: ^0.6.8 - version: 0.6.8 - ethereumjs-util: - specifier: ^7.1.5 - version: 7.1.5 prettier: specifier: ^2.7.1 version: 2.7.1 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.16.8)(typescript@4.9.5) + version: 10.9.1(@types/node@18.16.8)(typescript@5.1.6) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 typescript: - specifier: ^4.8.4 - version: 4.9.5 + specifier: ^5.1.6 + version: 5.1.6 - packages/contracts: + packages/contract-types: dependencies: + '@ethersproject/abi': + specifier: ^5.7.0 + version: 5.7.0 '@ethersproject/bytes': - specifier: ^5.0.0 + specifier: ^5.7.0 version: 5.7.0 '@ethersproject/providers': - specifier: ^5.4.7 + specifier: ^5.7.0 version: 5.7.2 '@ethersproject/units': - specifier: ^5.4.7 + specifier: ^5.7.0 version: 5.7.0 + '@typechain/ethers-v5': + specifier: ^11.1.1 + version: 11.1.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6) ethers: - specifier: ^5.7.2 + specifier: ^5.7.0 version: 5.7.2 devDependencies: - '@babel/core': - specifier: ^7.11.6 - version: 7.19.6 - '@ethereum-waffle/mock-contract': - specifier: ^3.4.4 - version: 3.4.4 - '@ethersproject/abi': - specifier: ^5.0.0 - version: 5.7.0 - '@ethersproject/hdnode': - specifier: ^5.7.0 - version: 5.7.0 - '@iarna/toml': - specifier: ^2.2.5 - version: 2.2.5 - '@polkadot/api': - specifier: 10.7.1 - version: 10.7.1 - '@polkadot/types': - specifier: 10.7.1 - version: 10.7.1 - '@typechain/ethers-v5': - specifier: ^10.1.1 - version: 10.1.1(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.1.1)(typescript@4.9.5) - '@types/keccak': - specifier: ^3.0.1 - version: 3.0.1 - '@types/lodash': - specifier: ^4.14.186 - version: 4.14.187 - '@types/mocha': - specifier: ^10.0.0 - version: 10.0.0 '@types/node': specifier: ^18.13.0 version: 18.16.8 - '@types/secp256k1': - specifier: ^4.0.3 - version: 4.0.3 - '@types/seedrandom': - specifier: ^3.0.2 - version: 3.0.2 - '@typescript-eslint/eslint-plugin': - specifier: ^5.42.0 - version: 5.42.0(@typescript-eslint/parser@5.42.0)(eslint@8.26.0)(typescript@4.9.5) - '@typescript-eslint/parser': - specifier: ^5.42.0 - version: 5.42.0(eslint@8.26.0)(typescript@4.9.5) - bitfield: - specifier: ^4.1.0 - version: 4.1.0 - chai: - specifier: ^4.3.4 - version: 4.3.7 - chai-as-promised: - specifier: ^7.1.1 - version: 7.1.1(chai@4.3.7) - chai-bignumber: - specifier: ^3.0.0 - version: 3.1.0 - esbuild: - specifier: ^0.17.4 - version: 0.17.4 - eslint: - specifier: ^8.26.0 - version: 8.26.0 - eslint-config-prettier: - specifier: ^8.5.0 - version: 8.5.0(eslint@8.26.0) - ethereumjs-abi: - specifier: ^0.6.8 - version: 0.6.8 - ethereumjs-util: - specifier: ^7.0.10 - version: 7.1.5 - find-config: - specifier: ^1.0.0 - version: 1.0.0 - keccak: - specifier: ^3.0.2 - version: 3.0.3 - lodash: - specifier: ^4.17.21 - version: 4.17.21 - merkletreejs: - specifier: ^0.2.18 - version: 0.2.32 - mocha: - specifier: ^10.1.0 - version: 10.1.0 - prettier: - specifier: ^2.6.2 - version: 2.7.1 - prettier-plugin-solidity: - specifier: ^1.0.0 - version: 1.0.0(prettier@2.7.1) - rlp: - specifier: ^2.2.6 - version: 2.2.7 - secp256k1: - specifier: ^4.0.2 - version: 4.0.3 - seedrandom: - specifier: ^3.0.5 - version: 3.0.5 - solc: - specifier: ^0.7.6 - version: 0.7.6 - solhint: - specifier: ^3.3.7 - version: 3.3.7 - solidity-docgen: - specifier: ^0.5.10 - version: 0.5.17 - temp: - specifier: ^0.9.1 - version: 0.9.4 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@18.16.8)(typescript@4.9.5) - tsconfig-paths: - specifier: ^4.1.0 - version: 4.1.0 + version: 10.9.1(@types/node@18.16.8)(typescript@5.1.6) typechain: - specifier: ^8.1.1 - version: 8.1.1(typescript@4.9.5) + specifier: ^8.3.1 + version: 8.3.1(typescript@5.1.6) typescript: - specifier: ^4.3.2 - version: 4.9.5 - unique-filename: - specifier: ^1.1.1 - version: 1.1.1 + specifier: ^5.1.6 + version: 5.1.6 packages/test: devDependencies: @@ -215,19 +114,19 @@ importers: version: 1.8.0(c-kzg@1.1.3)(fastify@3.15.1) '@polkadot/api': specifier: ^10.7.1 - version: 10.7.1 + version: 10.9.1 '@polkadot/api-cli': specifier: ^0.54.4 version: 0.54.4 '@polkadot/types': specifier: ^10.7.1 - version: 10.7.1 + version: 10.9.1 '@polkadot/util': specifier: ^12.2.1 - version: 12.2.1 + version: 12.3.2 '@polkadot/util-crypto': specifier: ^12.2.1 - version: 12.2.1(@polkadot/util@12.2.1) + version: 12.3.2(@polkadot/util@12.3.2) '@types/keccak': specifier: ^3.0.1 version: 3.0.1 @@ -239,7 +138,7 @@ importers: version: 17.0.24 '@zombienet/cli': specifier: ^1.3.52 - version: 1.3.52(@polkadot/util@12.2.1)(@types/node@18.16.8) + version: 1.3.63(@polkadot/util@12.3.2)(@types/node@18.16.8) bignumber.js: specifier: ^9.1.1 version: 9.1.1 @@ -292,6 +191,100 @@ importers: specifier: ^17.7.2 version: 17.7.2 + packages/test-helpers: + dependencies: + '@ethersproject/abi': + specifier: ^5.0.0 + version: 5.7.0 + '@ethersproject/bytes': + specifier: ^5.0.0 + version: 5.7.0 + '@ethersproject/providers': + specifier: ^5.4.7 + version: 5.7.2 + '@ethersproject/units': + specifier: ^5.4.7 + version: 5.7.0 + '@polkadot/api': + specifier: ^10.9.1 + version: 10.9.1 + '@polkadot/types': + specifier: ^10.9.1 + version: 10.9.1 + '@snowbridge/contract-types': + specifier: workspace:* + version: link:../contract-types + '@typechain/ethers-v5': + specifier: ^10.1.1 + version: 10.1.1(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6) + '@types/keccak': + specifier: ^3.0.1 + version: 3.0.1 + '@types/lodash': + specifier: ^4.14.186 + version: 4.14.187 + '@types/node': + specifier: ^18.13.0 + version: 18.16.8 + '@types/secp256k1': + specifier: ^4.0.3 + version: 4.0.3 + '@types/seedrandom': + specifier: ^3.0.2 + version: 3.0.2 + bitfield: + specifier: ^4.1.0 + version: 4.1.0 + ethereumjs-abi: + specifier: ^0.6.8 + version: 0.6.8 + ethereumjs-util: + specifier: ^7.0.10 + version: 7.1.5 + ethers: + specifier: ^5.7.2 + version: 5.7.2 + keccak: + specifier: ^3.0.2 + version: 3.0.3 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + merkletreejs: + specifier: ^0.2.18 + version: 0.2.32 + rlp: + specifier: ^2.2.6 + version: 2.2.7 + secp256k1: + specifier: ^4.0.2 + version: 4.0.3 + seedrandom: + specifier: ^3.0.5 + version: 3.0.5 + devDependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^5.42.0 + version: 5.42.0(@typescript-eslint/parser@5.42.0)(eslint@8.26.0)(typescript@5.1.6) + '@typescript-eslint/parser': + specifier: ^5.42.0 + version: 5.42.0(eslint@8.26.0)(typescript@5.1.6) + eslint: + specifier: ^8.26.0 + version: 8.26.0 + eslint-config-prettier: + specifier: ^8.5.0 + version: 8.5.0(eslint@8.26.0) + ts-node: + specifier: ^10.9.1 + version: 10.9.1(@types/node@18.16.8)(typescript@5.1.6) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + typescript: + specifier: ^5.1.6 + version: 5.1.6 + packages: /@achingbrain/ip-address@8.1.0: @@ -324,209 +317,8 @@ packages: dependencies: event-iterator: 2.0.0 freeport-promise: 2.0.0 - merge-options: 3.0.4 - xml2js: 0.5.0 - dev: true - - /@ampproject/remapping@2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.17 - dev: true - - /@babel/code-frame@7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: true - - /@babel/compat-data@7.20.1: - resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.19.6: - resolution: {integrity: sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.1 - '@babel/helper-compilation-targets': 7.20.0(@babel/core@7.19.6) - '@babel/helper-module-transforms': 7.19.6 - '@babel/helpers': 7.20.1 - '@babel/parser': 7.20.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.1 - '@babel/types': 7.20.0 - convert-source-map: 1.9.0 - debug: 4.3.4(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.20.1: - resolution: {integrity: sha512-u1dMdBUmA7Z0rBB97xh8pIhviK7oItYOkjbsCxTWMknyvbQRBwX7/gn4JXurRdirWMFh+ZtYARqkA6ydogVZpg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - dev: true - - /@babel/helper-compilation-targets@7.20.0(@babel/core@7.19.6): - resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.20.1 - '@babel/core': 7.19.6 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - semver: 6.3.0 - dev: true - - /@babel/helper-environment-visitor@7.18.9: - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name@7.19.0: - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-hoist-variables@7.18.6: - resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-module-imports@7.18.6: - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-module-transforms@7.19.6: - resolution: {integrity: sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.19.4 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.1 - '@babel/types': 7.20.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-simple-access@7.19.4: - resolution: {integrity: sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-split-export-declaration@7.18.6: - resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-string-parser@7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.18.6: - resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.20.1: - resolution: {integrity: sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.1 - '@babel/types': 7.20.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser@7.20.1: - resolution: {integrity: sha512-hp0AYxaZJhxULfM1zyp7Wgr+pSUKBcP3M+PHnSzWGdXOzg/kHWIgiUWARvubhUKGOEw3xqY4x+lyZ9ytBVcELw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/template@7.18.10: - resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.20.1 - '@babel/types': 7.20.0 - dev: true - - /@babel/traverse@7.20.1: - resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.1 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.1 - '@babel/types': 7.20.0 - debug: 4.3.4(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.20.0: - resolution: {integrity: sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 + merge-options: 3.0.4 + xml2js: 0.5.0 dev: true /@chainsafe/as-chacha20poly1305@0.1.0: @@ -549,7 +341,7 @@ packages: /@chainsafe/bls-hd-key@0.3.0: resolution: {integrity: sha512-LsYYnfBEEmqGFPDm8hQN3Kc+v9wPFnhn+CToD403KEynUiUSHKLAf5B6UCY5eooShDOcaGCUgAUhIw1CmpEf3Q==} dependencies: - '@noble/hashes': 1.3.0 + '@noble/hashes': 1.3.1 dev: true /@chainsafe/bls-keygen@0.3.0: @@ -565,7 +357,7 @@ packages: resolution: {integrity: sha512-wqtuj4G/sWpIugJW1mb/nSTwcTuZKqB3DS3ANUIOn7pva8EB6LfxgIL34o4qk3lti/8Mdxqtqc2n4xRszrNdzA==} dependencies: '@chainsafe/bls-hd-key': 0.3.0 - '@noble/hashes': 1.3.0 + '@noble/hashes': 1.3.1 '@scure/bip39': 1.2.0 dev: true @@ -815,204 +607,6 @@ packages: kuler: 2.0.0 dev: true - /@esbuild/android-arm64@0.17.4: - resolution: {integrity: sha512-91VwDrl4EpxBCiG6h2LZZEkuNvVZYJkv2T9gyLG/mhGG1qrM7i5SwUcg/hlSPnL/4hDT0TFcF35/XMGSn0bemg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm@0.17.4: - resolution: {integrity: sha512-R9GCe2xl2XDSc2XbQB63mFiFXHIVkOP+ltIxICKXqUPrFX97z6Z7vONCLQM1pSOLGqfLrGi3B7nbhxmFY/fomg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64@0.17.4: - resolution: {integrity: sha512-mGSqhEPL7029XL7QHNPxPs15JVa02hvZvysUcyMP9UXdGFwncl2WU0bqx+Ysgzd+WAbv8rfNa73QveOxAnAM2w==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64@0.17.4: - resolution: {integrity: sha512-tTyJRM9dHvlMPt1KrBFVB5OW1kXOsRNvAPtbzoKazd5RhD5/wKlXk1qR2MpaZRYwf4WDMadt0Pv0GwxB41CVow==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64@0.17.4: - resolution: {integrity: sha512-phQuC2Imrb3TjOJwLN8EO50nb2FHe8Ew0OwgZDH1SV6asIPGudnwTQtighDF2EAYlXChLoMJwqjAp4vAaACq6w==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64@0.17.4: - resolution: {integrity: sha512-oH6JUZkocgmjzzYaP5juERLpJQSwazdjZrTPgLRmAU2bzJ688x0vfMB/WTv4r58RiecdHvXOPC46VtsMy/mepg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64@0.17.4: - resolution: {integrity: sha512-U4iWGn/9TrAfpAdfd56eO0pRxIgb0a8Wj9jClrhT8hvZnOnS4dfMPW7o4fn15D/KqoiVYHRm43jjBaTt3g/2KA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64@0.17.4: - resolution: {integrity: sha512-UkGfQvYlwOaeYJzZG4cLV0hCASzQZnKNktRXUo3/BMZvdau40AOz9GzmGA063n1piq6VrFFh43apRDQx8hMP2w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm@0.17.4: - resolution: {integrity: sha512-S2s9xWTGMTa/fG5EyMGDeL0wrWVgOSQcNddJWgu6rG1NCSXJHs76ZP9AsxjB3f2nZow9fWOyApklIgiTGZKhiw==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32@0.17.4: - resolution: {integrity: sha512-3lqFi4VFo/Vwvn77FZXeLd0ctolIJH/uXkH3yNgEk89Eh6D3XXAC9/iTPEzeEpsNE5IqGIsFa5Z0iPeOh25IyA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64@0.17.4: - resolution: {integrity: sha512-HqpWZkVslDHIwdQ9D+gk7NuAulgQvRxF9no54ut/M55KEb3mi7sQS3GwpPJzSyzzP0UkjQVN7/tbk88/CaX4EQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el@0.17.4: - resolution: {integrity: sha512-d/nMCKKh/SVDbqR9ju+b78vOr0tNXtfBjcp5vfHONCCOAL9ad8gN9dC/u+UnH939pz7wO+0u/x9y1MaZcb/lKA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64@0.17.4: - resolution: {integrity: sha512-lOD9p2dmjZcNiTU+sGe9Nn6G3aYw3k0HBJies1PU0j5IGfp6tdKOQ6mzfACRFCqXjnBuTqK7eTYpwx09O5LLfg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64@0.17.4: - resolution: {integrity: sha512-mTGnwWwVshAjGsd8rP+K6583cPDgxOunsqqldEYij7T5/ysluMHKqUIT4TJHfrDFadUwrghAL6QjER4FeqQXoA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x@0.17.4: - resolution: {integrity: sha512-AQYuUGp50XM29/N/dehADxvc2bUqDcoqrVuijop1Wv72SyxT6dDB9wjUxuPZm2HwIM876UoNNBMVd+iX/UTKVQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64@0.17.4: - resolution: {integrity: sha512-+AsFBwKgQuhV2shfGgA9YloxLDVjXgUEWZum7glR5lLmV94IThu/u2JZGxTgjYby6kyXEx8lKOqP5rTEVBR0Rw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64@0.17.4: - resolution: {integrity: sha512-zD1TKYX9553OiLS/qkXPMlWoELYkH/VkzRYNKEU+GwFiqkq0SuxsKnsCg5UCdxN3cqd+1KZ8SS3R+WG/Hxy2jQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64@0.17.4: - resolution: {integrity: sha512-PY1NjEsLRhPEFFg1AV0/4Or/gR+q2dOb9s5rXcPuCjyHRzbt8vnHJl3vYj+641TgWZzTFmSUnZbzs1zwTzjeqw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64@0.17.4: - resolution: {integrity: sha512-B3Z7s8QZQW9tKGleMRXvVmwwLPAUoDCHs4WZ2ElVMWiortLJFowU1NjAhXOKjDgC7o9ByeVcwyOlJ+F2r6ZgmQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64@0.17.4: - resolution: {integrity: sha512-0HCu8R3mY/H5V7N6kdlsJkvrT591bO/oRZy8ztF1dhgNU5xD5tAh5bKByT1UjTGjp/VVBsl1PDQ3L18SfvtnBQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32@0.17.4: - resolution: {integrity: sha512-VUjhVDQycse1gLbe06pC/uaA0M+piQXJpdpNdhg8sPmeIZZqu5xPoGWVCmcsOO2gaM2cywuTYTHkXRozo3/Nkg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64@0.17.4: - resolution: {integrity: sha512-0kLAjs+xN5OjhTt/aUA6t48SfENSCKgGPfExADYTOo/UCn0ivxos9/anUVeSfg+L+2O9xkFxvJXIJfG+Q4sYSg==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@eslint/eslintrc@1.3.3: resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1030,17 +624,6 @@ packages: - supports-color dev: true - /@ethereum-waffle/mock-contract@3.4.4: - resolution: {integrity: sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA==} - engines: {node: '>=10.0'} - 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==} dependencies: @@ -1397,48 +980,15 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@iarna/toml@2.2.5: - resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} - dev: true - - /@jridgewell/gen-mapping@0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jridgewell/gen-mapping@0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 - dev: true - /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} dev: true - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - dev: true - /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: true - /@jridgewell/trace-mapping@0.3.17: - resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - /@jridgewell/trace-mapping@0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: @@ -2347,21 +1897,18 @@ packages: - supports-color dev: true - /@noble/curves@1.0.0: - resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} + /@noble/curves@1.1.0: + resolution: {integrity: sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==} dependencies: - '@noble/hashes': 1.3.0 - - /@noble/ed25519@1.7.1: - resolution: {integrity: sha512-Rk4SkJFaXZiznFyC/t77Q0NKS4FL7TLJJsVG2V2oiEq3kJVeTdxysEe/yRWSpnWMe808XRDJ+VFh5pt/FN5plw==} - dev: true + '@noble/hashes': 1.3.1 /@noble/ed25519@1.7.3: resolution: {integrity: sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==} dev: true - /@noble/hashes@1.3.0: - resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} + /@noble/hashes@1.3.1: + resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} + engines: {node: '>= 16'} /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -2518,174 +2065,55 @@ packages: engines: {node: '>= 8'} dev: true - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.13.0 - dev: true - - /@npmcli/fs@1.1.1: - resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} - dependencies: - '@gar/promisify': 1.1.3 - semver: 7.5.1 - dev: true - - /@npmcli/move-file@1.1.2: - resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} - engines: {node: '>=10'} - deprecated: This functionality has been moved to @npmcli/fs - dependencies: - mkdirp: 1.0.4 - rimraf: 3.0.2 - dev: true - - /@oclif/command@1.8.19(@oclif/config@1.18.5): - resolution: {integrity: sha512-4fB3VB877Bbw2eewl7rp4UPV45GtPFUlk9xGtafl28mD95dGiYYXzU+pLgqMkrEdEfn4/py+3YnE3uYu+djfRA==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@oclif/config': ^1 - dependencies: - '@oclif/config': 1.18.5 - '@oclif/errors': 1.3.6 - '@oclif/help': 1.0.3 - '@oclif/parser': 3.8.8 - debug: 4.3.4(supports-color@8.1.1) - semver: 7.5.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@oclif/config@1.18.5: - resolution: {integrity: sha512-R6dBedaUVn5jtAh79aaRm7jezx4l3V7Im9NORlLmudz5BL1foMeuXEvnqm+bMiejyexVA+oi9mto6YKZPzo/5Q==} - engines: {node: '>=8.0.0'} - dependencies: - '@oclif/errors': 1.3.6 - '@oclif/parser': 3.8.8 - debug: 4.3.4(supports-color@8.1.1) - globby: 11.1.0 - is-wsl: 2.2.0 - tslib: 2.5.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@oclif/core@1.20.2: - resolution: {integrity: sha512-c6CpDbDPS9UuKwGoajzsjrjfnwQywWEV3WI5FDvb87h0/WW2tGf1QwHUWgdKOojafEcMAa9DnP5j+mXdUTtpCg==} - engines: {node: '>=14.0.0'} - dependencies: - '@oclif/linewrap': 1.0.0 - '@oclif/screen': 3.0.3 - ansi-escapes: 4.3.2 - ansi-styles: 4.3.0 - cardinal: 2.1.1 - chalk: 4.1.2 - clean-stack: 3.0.1 - cli-progress: 3.12.0 - debug: 4.3.4(supports-color@8.1.1) - ejs: 3.1.8 - fs-extra: 9.1.0 - get-package-type: 0.1.0 - globby: 11.1.0 - hyperlinker: 1.0.0 - indent-string: 4.0.0 - is-wsl: 2.2.0 - js-yaml: 3.14.1 - natural-orderby: 2.0.3 - object-treeify: 1.1.33 - password-prompt: 1.1.2 - semver: 7.5.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - supports-color: 8.1.1 - supports-hyperlinks: 2.3.0 - tslib: 2.5.0 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - dev: true - - /@oclif/errors@1.3.6: - resolution: {integrity: sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ==} - engines: {node: '>=8.0.0'} - dependencies: - clean-stack: 3.0.1 - fs-extra: 8.1.0 - indent-string: 4.0.0 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /@oclif/help@1.0.3: - resolution: {integrity: sha512-AjjhSWFQkRb9rChEH+IRUmp0CxEacYpUbh+kQqtdCR9CDSsj2a3ibWjtMtJb4lFGAle6kVKfaal/juYe+6P5TQ==} - engines: {node: '>=8.0.0'} - dependencies: - '@oclif/config': 1.18.5 - '@oclif/errors': 1.3.6 - chalk: 4.1.2 - indent-string: 4.0.0 - lodash: 4.17.21 - string-width: 4.2.3 - strip-ansi: 6.0.1 - widest-line: 3.1.0 - wrap-ansi: 6.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@oclif/linewrap@1.0.0: - resolution: {integrity: sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==} - dev: true - - /@oclif/parser@3.8.8: - resolution: {integrity: sha512-OgqQAtpyq1XFJG3dvLl9aqiO+F5pubkzt7AivUDkNoa6/hNgVZ79vvTO8sqo5XAAhOm/fcTSerZ35OTnTJb1ng==} - engines: {node: '>=8.0.0'} + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} dependencies: - '@oclif/errors': 1.3.6 - '@oclif/linewrap': 1.0.0 - chalk: 4.1.2 - tslib: 2.5.0 + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 dev: true - /@oclif/plugin-help@5.1.17: - resolution: {integrity: sha512-yc35xn4lSkHTnS6ajolYAi9dVMWXsRRPPPNEfYF0Nq1bkKNnh3DEC1MS/iTWNEYC5JCVd4YAQ2/Ky2wqA2Ujiw==} - engines: {node: '>=12.0.0'} + /@npmcli/fs@1.1.1: + resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} dependencies: - '@oclif/core': 1.20.2 + '@gar/promisify': 1.1.3 + semver: 7.5.1 dev: true - /@oclif/screen@3.0.3: - resolution: {integrity: sha512-KX8gMYA9ujBPOd1HFsV9e0iEx7Uoj8AG/3YsW4TtWQTg4lJvr82qNm7o/cFQfYRIt+jw7Ew/4oL4A22zOT+IRA==} - engines: {node: '>=12.0.0'} - deprecated: Deprecated in favor of @oclif/core + /@npmcli/move-file@1.1.2: + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + deprecated: This functionality has been moved to @npmcli/fs + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 dev: true - /@polkadot/api-augment@10.7.1: - resolution: {integrity: sha512-VX4sUXV0bq0/pVFTzVUhSLvcGMZKuUTrajv6bZMPBbSjhIN0aWPX2d+/dsHEaNnqnROU0P/40i0oeFMfjv4tzg==} + /@polkadot/api-augment@10.9.1: + resolution: {integrity: sha512-kRZZvCFVcN4hAH4dJ+Qzfdy27/4EEq3oLDf3ihj0LTVrAezSWcKPGE3EVFy+Mn6Lo4SUc7RVyoKvIUhSk2l4Dg==} engines: {node: '>=16'} dependencies: - '@polkadot/api-base': 10.7.1 - '@polkadot/rpc-augment': 10.7.1 - '@polkadot/types': 10.7.1 - '@polkadot/types-augment': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/api-base': 10.9.1 + '@polkadot/rpc-augment': 10.9.1 + '@polkadot/types': 10.9.1 + '@polkadot/types-augment': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - /@polkadot/api-base@10.7.1: - resolution: {integrity: sha512-bgNjwd7I67kSxLzQGpwpGq3nZYb0PdnroAqNNmKVtNms0JGdRsX8j06nJ89XRXDq+bwOXaDslrC3VKgrCm36DA==} + /@polkadot/api-base@10.9.1: + resolution: {integrity: sha512-Q3m2KzlceMK2kX8bhnUZWk3RT6emmijeeFZZQgCePpEcrSeNjnqG4qjuTPgkveaOkUT8MAoDc5Avuzcc2jlW9g==} engines: {node: '>=16'} dependencies: - '@polkadot/rpc-core': 10.7.1 - '@polkadot/types': 10.7.1 - '@polkadot/util': 12.2.1 + '@polkadot/rpc-core': 10.9.1 + '@polkadot/types': 10.9.1 + '@polkadot/util': 12.3.2 rxjs: 7.8.1 - tslib: 2.5.0 + tslib: 2.6.1 transitivePeerDependencies: - bufferutil - supports-color @@ -2696,12 +2124,12 @@ packages: engines: {node: '>=16'} hasBin: true dependencies: - '@polkadot/api': 10.7.1 - '@polkadot/keyring': 12.2.1(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1) - '@polkadot/types': 10.7.1 - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) - tslib: 2.5.0 + '@polkadot/api': 10.9.1 + '@polkadot/keyring': 12.3.2(@polkadot/util-crypto@12.3.2)(@polkadot/util@12.3.2) + '@polkadot/types': 10.9.1 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) + tslib: 2.6.1 yargs: 17.7.2 transitivePeerDependencies: - bufferutil @@ -2709,127 +2137,115 @@ packages: - utf-8-validate dev: true - /@polkadot/api-derive@10.7.1: - resolution: {integrity: sha512-pyNRe8OrA6iNuYKGO/BlxGmKavzohwAAweVphuZnbWfVUKjuRZEgclHYRq/O+pKrPMm3eIbsHVvFlMnIU+rxFw==} + /@polkadot/api-derive@10.9.1: + resolution: {integrity: sha512-mRud1UZCFIc4Z63qAoGSIHh/foyUYADfy1RQYCmPpeFKfIdCIrHpd7xFdJXTOMYOS0BwlM6u4qli/ZT4XigezQ==} engines: {node: '>=16'} dependencies: - '@polkadot/api': 10.7.1 - '@polkadot/api-augment': 10.7.1 - '@polkadot/api-base': 10.7.1 - '@polkadot/rpc-core': 10.7.1 - '@polkadot/types': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) + '@polkadot/api': 10.9.1 + '@polkadot/api-augment': 10.9.1 + '@polkadot/api-base': 10.9.1 + '@polkadot/rpc-core': 10.9.1 + '@polkadot/types': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) rxjs: 7.8.1 - tslib: 2.5.0 + tslib: 2.6.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - /@polkadot/api@10.7.1: - resolution: {integrity: sha512-6jVYCVlKvQC1HctlZdH3fg28yWb5Wv7IMJn055j66aE+D54z+P8VYdUx17rZsUCWjg6lMlVyzybM9aTm5TE8Sw==} + /@polkadot/api@10.9.1: + resolution: {integrity: sha512-ND/2UqZBWvtt4PfV03OStTKg0mxmPk4UpMAgJKutdgsz/wP9CYJ1KbjwFgPNekL9JnzbKQsWyQNPVrcw7kQk8A==} engines: {node: '>=16'} dependencies: - '@polkadot/api-augment': 10.7.1 - '@polkadot/api-base': 10.7.1 - '@polkadot/api-derive': 10.7.1 - '@polkadot/keyring': 12.2.1(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1) - '@polkadot/rpc-augment': 10.7.1 - '@polkadot/rpc-core': 10.7.1 - '@polkadot/rpc-provider': 10.7.1 - '@polkadot/types': 10.7.1 - '@polkadot/types-augment': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/types-create': 10.7.1 - '@polkadot/types-known': 10.7.1 - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) + '@polkadot/api-augment': 10.9.1 + '@polkadot/api-base': 10.9.1 + '@polkadot/api-derive': 10.9.1 + '@polkadot/keyring': 12.3.2(@polkadot/util-crypto@12.3.2)(@polkadot/util@12.3.2) + '@polkadot/rpc-augment': 10.9.1 + '@polkadot/rpc-core': 10.9.1 + '@polkadot/rpc-provider': 10.9.1 + '@polkadot/types': 10.9.1 + '@polkadot/types-augment': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/types-create': 10.9.1 + '@polkadot/types-known': 10.9.1 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) eventemitter3: 5.0.1 rxjs: 7.8.1 - tslib: 2.5.0 + tslib: 2.6.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - /@polkadot/keyring@12.1.2(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1): - resolution: {integrity: sha512-HskFoZwLwRWPthEQK50uOiOsbdIt0AY3gcrDmSS2ltkpUDY9qzlb/fAj0+QGtTrK36v5gHT8OD56Pd4l0FDMFw==} - engines: {node: '>=16'} - peerDependencies: - '@polkadot/util': 12.1.2 - '@polkadot/util-crypto': 12.1.2 - dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) - tslib: 2.5.0 - dev: true - - /@polkadot/keyring@12.2.1(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1): - resolution: {integrity: sha512-YqgpU+97OZgnSUL56DEMib937Dpb1bTTDPYHhBiN1yNCKod7UboWXIe4xPh+1Kzugum+dEyPpdV+fHH10rtDzw==} + /@polkadot/keyring@12.3.2(@polkadot/util-crypto@12.3.2)(@polkadot/util@12.3.2): + resolution: {integrity: sha512-NTdtDeI0DP9l/45hXynNABeP5VB8piw5YR+CbUxK2e36xpJWVXwbcOepzslg5ghE9rs8UKJb30Z/HqTU4sBY0Q==} engines: {node: '>=16'} peerDependencies: - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2 dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) + tslib: 2.6.1 - /@polkadot/networks@12.2.1: - resolution: {integrity: sha512-lYLvFv6iQ2UzkP66zJfsiTo2goeaNeKuwiaGoRoFrDwdwVeZK/+rCsz1uAyvbwmpZIaK8K+dTlSBVWlFoAkgcA==} + /@polkadot/networks@12.3.2: + resolution: {integrity: sha512-uCkyybKoeEm1daKr0uT/9oNDHDDzCy2/ZdVl346hQqfdR1Ct3BaxMjxqvdmb5N8aCw0cBWSfgsxAYtw8ESmllQ==} engines: {node: '>=16'} dependencies: - '@polkadot/util': 12.2.1 + '@polkadot/util': 12.3.2 '@substrate/ss58-registry': 1.40.0 - tslib: 2.5.0 + tslib: 2.6.1 - /@polkadot/rpc-augment@10.7.1: - resolution: {integrity: sha512-D4msTT74PaiI3M8E8vhXdN9oNyXaKcTpTWzfJvP5m8fj0YrKS+zoZotePyiry5n/Pam2RzwYdiu/vktuDuvn9w==} + /@polkadot/rpc-augment@10.9.1: + resolution: {integrity: sha512-MaLHkNlyqN20ZRYr6uNd1BZr1OsrnX9qLAmsl0mcrri1vPGRH6VHjfFH1RBLkikpWD82v17g0l2hLwdV1ZHMcw==} engines: {node: '>=16'} dependencies: - '@polkadot/rpc-core': 10.7.1 - '@polkadot/types': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/rpc-core': 10.9.1 + '@polkadot/types': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - /@polkadot/rpc-core@10.7.1: - resolution: {integrity: sha512-XIK28zCVmEpSgnB1DomXNdfMYKUTP5h/bnb+oaWeNUxFxBQtmO1a9UNlZG6thsnma2jlNFVzB0ihR3xoTkka0A==} + /@polkadot/rpc-core@10.9.1: + resolution: {integrity: sha512-ZtA8B8SfXSAwVkBlCcKRHw0eSM7ec/sbiNOM5GasXPeRujUgT7lOwSH2GbUZSqe9RfRDMp6DvO9c2JoGc3LLWw==} engines: {node: '>=16'} dependencies: - '@polkadot/rpc-augment': 10.7.1 - '@polkadot/rpc-provider': 10.7.1 - '@polkadot/types': 10.7.1 - '@polkadot/util': 12.2.1 + '@polkadot/rpc-augment': 10.9.1 + '@polkadot/rpc-provider': 10.9.1 + '@polkadot/types': 10.9.1 + '@polkadot/util': 12.3.2 rxjs: 7.8.1 - tslib: 2.5.0 + tslib: 2.6.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - /@polkadot/rpc-provider@10.7.1: - resolution: {integrity: sha512-FVaoqtPLb9uhDQb9bE2KSnDqzApsb/hpN57VcylbiUsSACBARGBWrHNAN5rQ8TFN2H6Uv8SqdxTsHeM74Ny2mw==} + /@polkadot/rpc-provider@10.9.1: + resolution: {integrity: sha512-4QzT2QzD+320+eT6b79sGAA85Tt3Bb8fQvse4r5Mom2iiBd2SO81vOhxSAOaIe4GUsw25VzFJmsbe7+OObItdg==} engines: {node: '>=16'} dependencies: - '@polkadot/keyring': 12.2.1(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1) - '@polkadot/types': 10.7.1 - '@polkadot/types-support': 10.7.1 - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) - '@polkadot/x-fetch': 12.2.1 - '@polkadot/x-global': 12.2.1 - '@polkadot/x-ws': 12.2.1 + '@polkadot/keyring': 12.3.2(@polkadot/util-crypto@12.3.2)(@polkadot/util@12.3.2) + '@polkadot/types': 10.9.1 + '@polkadot/types-support': 10.9.1 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) + '@polkadot/x-fetch': 12.3.2 + '@polkadot/x-global': 12.3.2 + '@polkadot/x-ws': 12.3.2 eventemitter3: 5.0.1 mock-socket: 9.2.1 nock: 13.3.1 - tslib: 2.5.0 + tslib: 2.6.1 optionalDependencies: '@substrate/connect': 0.7.26 transitivePeerDependencies: @@ -2837,215 +2253,215 @@ packages: - supports-color - utf-8-validate - /@polkadot/types-augment@10.7.1: - resolution: {integrity: sha512-8Yr3iNA9ZU6S0CdR6njM0hx4EBgsm5lZJtytQ8rSxfe8zYOLnh8lz9QLF+iyI+KNFAFwPwfgQ5QwO6zRd8WT+Q==} + /@polkadot/types-augment@10.9.1: + resolution: {integrity: sha512-OY9/jTMFRFqYdkUnfcGwqMLC64A0Q25bjvCuVQCVjsPFKE3wl0Kt5rNT01eV2UmLXrR6fY0xWbR2w80bLA7CIQ==} engines: {node: '>=16'} dependencies: - '@polkadot/types': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/types': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 - /@polkadot/types-codec@10.7.1: - resolution: {integrity: sha512-3VoR1JXFuwt3MQ+E7Vds0UsSRwytS9yo0GtgfP9Nmwt8neQE8JHEd/nAb4JrJFozr3bNRTj+A94wbYk/XB6VKA==} + /@polkadot/types-codec@10.9.1: + resolution: {integrity: sha512-mJ5OegKGraY1FLvEa8FopRCr3pQrhDkcn5RNOjmgJQozENVeRaxhk0NwxYz7IojFvSDnKnc6lNQfKaaSe5pLHg==} engines: {node: '>=16'} dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/x-bigint': 12.2.1 - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/x-bigint': 12.3.2 + tslib: 2.6.1 - /@polkadot/types-create@10.7.1: - resolution: {integrity: sha512-DJM7Rog2H7XNbGB18s1PY14yfgRNTIZVzHJxkdkXg5eXDWNmrVbwJFKP8gc469cpND+gooDAJeZ5gToiJEb4Hw==} + /@polkadot/types-create@10.9.1: + resolution: {integrity: sha512-OVz50MGTTuiuVnRP/zAx4CTuLioc0hsiwNwqN2lNhmIJGtnQ4Vy/7mQRsIWehiYz6g0Vzzm5B3qWkTXO1NSN5w==} engines: {node: '>=16'} dependencies: - '@polkadot/types-codec': 10.7.1 - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/types-codec': 10.9.1 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 - /@polkadot/types-known@10.7.1: - resolution: {integrity: sha512-4lff8uE6OcHsvhJYS6/feKnkDGnFd6jOSpi7d5WYDnxTpTbfvaS8UmZ1ZB9P3TjimrnnX+yV/pqFQV9TMA0bjA==} + /@polkadot/types-known@10.9.1: + resolution: {integrity: sha512-zCMVWc4pJtkbMFPu72bD4IhvV/gkHXPX3C5uu92WdmCfnn0vEIEsMKWlVXVVvQQZKAqvs/awpqIfrUtEViOGEA==} engines: {node: '>=16'} dependencies: - '@polkadot/networks': 12.2.1 - '@polkadot/types': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/types-create': 10.7.1 - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/networks': 12.3.2 + '@polkadot/types': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/types-create': 10.9.1 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 - /@polkadot/types-support@10.7.1: - resolution: {integrity: sha512-E7bJfqI9ajCsidRjHiIHTil6av+M+LVfiO9viPjA4PhMp6RIuH6jZ9xUZ6S6hM25zqDwnxtGjx3CPARAx6dwLg==} + /@polkadot/types-support@10.9.1: + resolution: {integrity: sha512-XsieuLDsszvMZQlleacQBfx07i/JkwQV/UxH9q8Hz7Okmaz9pEVEW1h3ka2/cPuC7a4l32JhaORBUYshBZNdJg==} engines: {node: '>=16'} dependencies: - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 - /@polkadot/types@10.7.1: - resolution: {integrity: sha512-Bb1DiYya0jLVYjyvOeJppJJikj6v1XXyHsj1OpvKK/ErnIGX0Esj8UyakmKxvDf2y0fn4VabCwXviuUIZhUTFg==} + /@polkadot/types@10.9.1: + resolution: {integrity: sha512-AG33i2ZGGfq7u+5rkAdGrXAQHHl844/Yv+junH5ZzX69xiCoWO1bH/yzDUNBdpki2GlACWvF9nLYh3F2tVF93w==} engines: {node: '>=16'} dependencies: - '@polkadot/keyring': 12.2.1(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1) - '@polkadot/types-augment': 10.7.1 - '@polkadot/types-codec': 10.7.1 - '@polkadot/types-create': 10.7.1 - '@polkadot/util': 12.2.1 - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) + '@polkadot/keyring': 12.3.2(@polkadot/util-crypto@12.3.2)(@polkadot/util@12.3.2) + '@polkadot/types-augment': 10.9.1 + '@polkadot/types-codec': 10.9.1 + '@polkadot/types-create': 10.9.1 + '@polkadot/util': 12.3.2 + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) rxjs: 7.8.1 - tslib: 2.5.0 + tslib: 2.6.1 - /@polkadot/util-crypto@12.2.1(@polkadot/util@12.2.1): - resolution: {integrity: sha512-MFh7Sdm7/G9ot5eIBZGuQXTYP/EbOCh1+ODyygp9/TjWAmJZMq1J73Uqk4KmzkwpDBpNZO8TGjiYwL8lR6BnGg==} + /@polkadot/util-crypto@12.3.2(@polkadot/util@12.3.2): + resolution: {integrity: sha512-pTpx+YxolY0BDT4RcGmgeKbHHD/dI6Ll9xRsqmVdIjpcVVY20uDNTyXs81ZNtfKgyod1y9JQkfNv2Dz9iEpTkQ==} engines: {node: '>=16'} peerDependencies: - '@polkadot/util': 12.2.1 - dependencies: - '@noble/curves': 1.0.0 - '@noble/hashes': 1.3.0 - '@polkadot/networks': 12.2.1 - '@polkadot/util': 12.2.1 - '@polkadot/wasm-crypto': 7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1) - '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/x-bigint': 12.2.1 - '@polkadot/x-randomvalues': 12.2.1(@polkadot/util@12.2.1)(@polkadot/wasm-util@7.2.1) + '@polkadot/util': 12.3.2 + dependencies: + '@noble/curves': 1.1.0 + '@noble/hashes': 1.3.1 + '@polkadot/networks': 12.3.2 + '@polkadot/util': 12.3.2 + '@polkadot/wasm-crypto': 7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2) + '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/x-bigint': 12.3.2 + '@polkadot/x-randomvalues': 12.3.2(@polkadot/util@12.3.2)(@polkadot/wasm-util@7.2.1) '@scure/base': 1.1.1 - tslib: 2.5.0 + tslib: 2.6.1 - /@polkadot/util@12.2.1: - resolution: {integrity: sha512-MQmPx9aCX4GTpDY/USUQywXRyaDbaibg4V1+c/CoRTsoDu+XHNM8G3lpabdNAYKZrtxg+3/1bTS0ojm6ANSQRw==} + /@polkadot/util@12.3.2: + resolution: {integrity: sha512-y/JShcGyOamCUiSIg++XZuLHt1ktSKBaSH2K5Nw5NXlgP0+7am+GZzqPB8fQ4qhYLruEOv+YRiz0GC1Zr9S+wg==} engines: {node: '>=16'} dependencies: - '@polkadot/x-bigint': 12.2.1 - '@polkadot/x-global': 12.2.1 - '@polkadot/x-textdecoder': 12.2.1 - '@polkadot/x-textencoder': 12.2.1 + '@polkadot/x-bigint': 12.3.2 + '@polkadot/x-global': 12.3.2 + '@polkadot/x-textdecoder': 12.3.2 + '@polkadot/x-textencoder': 12.3.2 '@types/bn.js': 5.1.1 bn.js: 5.2.1 - tslib: 2.5.0 + tslib: 2.6.1 - /@polkadot/wasm-bridge@7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1): + /@polkadot/wasm-bridge@7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2): resolution: {integrity: sha512-uV/LHREDBGBbHrrv7HTki+Klw0PYZzFomagFWII4lp6Toj/VCvRh5WMzooVC+g/XsBGosAwrvBhoModabyHx+A==} engines: {node: '>=16'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/x-randomvalues': 12.2.1(@polkadot/util@12.2.1)(@polkadot/wasm-util@7.2.1) - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/x-randomvalues': 12.3.2(@polkadot/util@12.3.2)(@polkadot/wasm-util@7.2.1) + tslib: 2.6.1 - /@polkadot/wasm-crypto-asmjs@7.2.1(@polkadot/util@12.2.1): + /@polkadot/wasm-crypto-asmjs@7.2.1(@polkadot/util@12.3.2): resolution: {integrity: sha512-z/d21bmxyVfkzGsKef/FWswKX02x5lK97f4NPBZ9XBeiFkmzlXhdSnu58/+b1sKsRAGdW/Rn/rTNRDhW0GqCAg==} engines: {node: '>=16'} peerDependencies: '@polkadot/util': '*' dependencies: - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 - /@polkadot/wasm-crypto-init@7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1): + /@polkadot/wasm-crypto-init@7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2): resolution: {integrity: sha512-GcEXtwN9LcSf32V9zSaYjHImFw16hCyo2Xzg4GLLDPPeaAAfbFr2oQMgwyDbvBrBjLKHVHjsPZyGhXae831amw==} engines: {node: '>=16'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/wasm-bridge': 7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1) - '@polkadot/wasm-crypto-asmjs': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/wasm-crypto-wasm': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/x-randomvalues': 12.2.1(@polkadot/util@12.2.1)(@polkadot/wasm-util@7.2.1) - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/wasm-bridge': 7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2) + '@polkadot/wasm-crypto-asmjs': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/wasm-crypto-wasm': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/x-randomvalues': 12.3.2(@polkadot/util@12.3.2)(@polkadot/wasm-util@7.2.1) + tslib: 2.6.1 - /@polkadot/wasm-crypto-wasm@7.2.1(@polkadot/util@12.2.1): + /@polkadot/wasm-crypto-wasm@7.2.1(@polkadot/util@12.3.2): resolution: {integrity: sha512-DqyXE4rSD0CVlLIw88B58+HHNyrvm+JAnYyuEDYZwCvzUWOCNos/DDg9wi/K39VAIsCCKDmwKqkkfIofuOj/lA==} engines: {node: '>=16'} peerDependencies: '@polkadot/util': '*' dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.2.1) - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.3.2) + tslib: 2.6.1 - /@polkadot/wasm-crypto@7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1): + /@polkadot/wasm-crypto@7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2): resolution: {integrity: sha512-SA2+33S9TAwGhniKgztVN6pxUKpGfN4Tre/eUZGUfpgRkT92wIUT2GpGWQE+fCCqGQgADrNiBcwt6XwdPqMQ4Q==} engines: {node: '>=16'} peerDependencies: '@polkadot/util': '*' '@polkadot/x-randomvalues': '*' dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/wasm-bridge': 7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1) - '@polkadot/wasm-crypto-asmjs': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/wasm-crypto-init': 7.2.1(@polkadot/util@12.2.1)(@polkadot/x-randomvalues@12.2.1) - '@polkadot/wasm-crypto-wasm': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/x-randomvalues': 12.2.1(@polkadot/util@12.2.1)(@polkadot/wasm-util@7.2.1) - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/wasm-bridge': 7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2) + '@polkadot/wasm-crypto-asmjs': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/wasm-crypto-init': 7.2.1(@polkadot/util@12.3.2)(@polkadot/x-randomvalues@12.3.2) + '@polkadot/wasm-crypto-wasm': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/x-randomvalues': 12.3.2(@polkadot/util@12.3.2)(@polkadot/wasm-util@7.2.1) + tslib: 2.6.1 - /@polkadot/wasm-util@7.2.1(@polkadot/util@12.2.1): + /@polkadot/wasm-util@7.2.1(@polkadot/util@12.3.2): resolution: {integrity: sha512-FBSn/3aYJzhN0sYAYhHB8y9JL8mVgxLy4M1kUXYbyo+8GLRQEN5rns8Vcb8TAlIzBWgVTOOptYBvxo0oj0h7Og==} engines: {node: '>=16'} peerDependencies: '@polkadot/util': '*' dependencies: - '@polkadot/util': 12.2.1 - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + tslib: 2.6.1 - /@polkadot/x-bigint@12.2.1: - resolution: {integrity: sha512-3cZLsV8kU1MFOTcyloeg61CF+qdBkbZxWZJkSjh4AGlPXy+2tKwwoBPExxfCWXK61+Lo/q3/U1+lln8DSBCI2A==} + /@polkadot/x-bigint@12.3.2: + resolution: {integrity: sha512-JLqLgfGXe/x+hZJETd5ZqfpVsbwyMsH5Nn1Q20ineMMjXN/ig+kVR8Mc15LXBMuw4g7LldFW6UUrotWnuMI8Yw==} engines: {node: '>=16'} dependencies: - '@polkadot/x-global': 12.2.1 - tslib: 2.5.0 + '@polkadot/x-global': 12.3.2 + tslib: 2.6.1 - /@polkadot/x-fetch@12.2.1: - resolution: {integrity: sha512-N2MIcn1g7LVZLZNDEkRkDD/LRY680PFqxziRoqb11SV52kRe6oVsdMIfaWH77UheniRR3br8YiQMUdvBVkak9Q==} + /@polkadot/x-fetch@12.3.2: + resolution: {integrity: sha512-3IEuZ5S+RI/t33NsdPLIIa5COfDCfpUW2sbaByEczn75aD1jLqJZSEDwiBniJ2osyNd4uUxBf6e5jw7LAZeZJg==} engines: {node: '>=16'} dependencies: - '@polkadot/x-global': 12.2.1 + '@polkadot/x-global': 12.3.2 node-fetch: 3.3.1 - tslib: 2.5.0 + tslib: 2.6.1 - /@polkadot/x-global@12.2.1: - resolution: {integrity: sha512-JNMziAZjvfzMrXASuBPCvSzEqlhsgw0x95SOBtqJWsxmbCMAiZbYAC51vI1B9Z9wiKuzPtSh9Sk7YHsUOGCrIQ==} + /@polkadot/x-global@12.3.2: + resolution: {integrity: sha512-yVZq6oIegjlyh5rUZiTklgu+fL+W/DG1ypEa02683tUCB3avV5cA3PAHKptMSlb6FpweHu37lKKrqfAWrraDxg==} engines: {node: '>=16'} dependencies: - tslib: 2.5.0 + tslib: 2.6.1 - /@polkadot/x-randomvalues@12.2.1(@polkadot/util@12.2.1)(@polkadot/wasm-util@7.2.1): - resolution: {integrity: sha512-NwSDLcLjgHa0C7Un54Yhg2/E3Y/PcVfW5QNB9TDyzDbkmod3ziaVhh0iWG0sOmm26K6Q3phY+0uYt0etq0Gu3w==} + /@polkadot/x-randomvalues@12.3.2(@polkadot/util@12.3.2)(@polkadot/wasm-util@7.2.1): + resolution: {integrity: sha512-ywjIs8CWpvOGmq+3cGCNPOHxAjPHdBUiXyDccftx5BRVdmtbt36gK/V84bKr6Xs73FGu0jprUAOSRRsLZX/3dg==} engines: {node: '>=16'} peerDependencies: - '@polkadot/util': 12.2.1 + '@polkadot/util': 12.3.2 '@polkadot/wasm-util': '*' dependencies: - '@polkadot/util': 12.2.1 - '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.2.1) - '@polkadot/x-global': 12.2.1 - tslib: 2.5.0 + '@polkadot/util': 12.3.2 + '@polkadot/wasm-util': 7.2.1(@polkadot/util@12.3.2) + '@polkadot/x-global': 12.3.2 + tslib: 2.6.1 - /@polkadot/x-textdecoder@12.2.1: - resolution: {integrity: sha512-5nQCIwyaGS0fXU2cbtMOSjFo0yTw1Z94m/UC+Gu5lm3ZU+kK4DpKFxhfLQORWAbvQkn12chRj3LI5Gm944hcrQ==} + /@polkadot/x-textdecoder@12.3.2: + resolution: {integrity: sha512-lY5bfA5xArJRWEJlYOlQQMJeTjWD8s0yMhchirVgf5xj8Id9vPGeUoneH+VFDEwgXxrqBvDFJ4smN4T/r6a/fg==} engines: {node: '>=16'} dependencies: - '@polkadot/x-global': 12.2.1 - tslib: 2.5.0 + '@polkadot/x-global': 12.3.2 + tslib: 2.6.1 - /@polkadot/x-textencoder@12.2.1: - resolution: {integrity: sha512-Ou6OXypRsJloK5a7Kn7re3ImqcL26h22fVw1cNv4fsTgkRFUdJDgPux2TpCZ3N+cyrfGVv42xKYFbdKMQCczjg==} + /@polkadot/x-textencoder@12.3.2: + resolution: {integrity: sha512-iP3qEBiHzBckQ9zeY7ZHRWuu7mCEg5SMpOugs6UODRk8sx6KHzGQYlghBbWLit0uppPDVE0ifEwZ2n73djJHWQ==} engines: {node: '>=16'} dependencies: - '@polkadot/x-global': 12.2.1 - tslib: 2.5.0 + '@polkadot/x-global': 12.3.2 + tslib: 2.6.1 - /@polkadot/x-ws@12.2.1: - resolution: {integrity: sha512-jPfNR/QFwPmXCk9hGEAyCo50xBNHm3s+XavmpHEKQSulnLn5des5X/pKn+g8ttaO9nqrXYnUFO6VEmILgUa/IQ==} + /@polkadot/x-ws@12.3.2: + resolution: {integrity: sha512-yM9Z64pLNlHpJE43+Xtr+iUXmYpFFY5u5hrke2PJt13O48H8f9Vb9cRaIh94appLyICoS0aekGhDkGH+MCspBA==} engines: {node: '>=16'} dependencies: - '@polkadot/x-global': 12.2.1 - tslib: 2.5.0 + '@polkadot/x-global': 12.3.2 + tslib: 2.6.1 ws: 8.13.0 transitivePeerDependencies: - bufferutil @@ -3154,7 +2570,7 @@ packages: /@scure/bip39@1.2.0: resolution: {integrity: sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg==} dependencies: - '@noble/hashes': 1.3.0 + '@noble/hashes': 1.3.1 '@scure/base': 1.1.1 dev: true @@ -3168,12 +2584,6 @@ packages: engines: {node: '>=14.16'} dev: true - /@solidity-parser/parser@0.14.5: - resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} - dependencies: - antlr4ts: 0.5.0-dev - dev: true - /@stablelib/aead@1.0.1: resolution: {integrity: sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==} dev: true @@ -3333,7 +2743,7 @@ packages: resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} dev: true - /@typechain/ethers-v5@10.1.1(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.1.1)(typescript@4.9.5): + /@typechain/ethers-v5@10.1.1(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6): resolution: {integrity: sha512-o6nffJBxwmeX1ZiZpdnP/tqGd/7M7iYvQC88ZXaFFoyAGh7eYncynzVjOJV0XmaKzAc6puqyqZrnva+gJbk4sw==} peerDependencies: '@ethersproject/abi': ^5.0.0 @@ -3348,10 +2758,28 @@ packages: '@ethersproject/providers': 5.7.2 ethers: 5.7.2 lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@4.9.5) - typechain: 8.1.1(typescript@4.9.5) - typescript: 4.9.5 - dev: true + ts-essentials: 7.0.3(typescript@5.1.6) + typechain: 8.3.1(typescript@5.1.6) + typescript: 5.1.6 + dev: false + + /@typechain/ethers-v5@11.1.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.1)(typescript@5.1.6): + resolution: {integrity: sha512-D9WyUrCJ4Z5Gg8T00HWLpuqn1CqSDXlCiUOOpLaWoCbnZrE2jSIOUwR9blBZNo6LE5058e3niVu6xk205Et7tg==} + peerDependencies: + '@ethersproject/abi': ^5.0.0 + '@ethersproject/providers': ^5.0.0 + ethers: ^5.1.3 + typechain: ^8.3.1 + typescript: '>=4.3.0' + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/providers': 5.7.2 + ethers: 5.7.2 + lodash: 4.17.21 + ts-essentials: 7.0.3(typescript@5.1.6) + typechain: 8.3.1(typescript@5.1.6) + typescript: 5.1.6 + dev: false /@types/abstract-leveldown@7.2.1: resolution: {integrity: sha512-YK8irIC+eMrrmtGx0H4ISn9GgzLd9dojZWJaMbjp1YHLl2VqqNFBNrL5Q3KjGf4VE3sf/4hmq6EhQZ7kZp1NoQ==} @@ -3361,7 +2789,7 @@ packages: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: '@types/node': 18.16.8 - dev: true + dev: false /@types/bn.js@5.1.1: resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} @@ -3404,7 +2832,6 @@ packages: resolution: {integrity: sha512-/MxAVmtyyeOvZ6dGf3ciLwFRuV5M8DRIyYNFGHYI6UyBW4/XqyO0LZw+JFMvaeY3cHItQAkELclBU1x5ank6mg==} dependencies: '@types/node': 18.16.8 - dev: true /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} @@ -3430,16 +2857,12 @@ packages: /@types/lodash@4.14.187: resolution: {integrity: sha512-MrO/xLXCaUgZy3y96C/iOsaIqZSeupyTImKClHunL5GrmaiII2VwvWmLBu2hwa0Kp0sV19CsyjtrTc/Fx8rg/A==} - dev: true + dev: false /@types/long@4.0.2: resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} dev: true - /@types/mocha@10.0.0: - resolution: {integrity: sha512-rADY+HtTOA52l9VZWtgQfn4p+UDVM2eDVkMZT1I6syp0YKxW2F9v+0pbRZLsvskhQv/vMb6ZfCay81GHbz5SHg==} - dev: true - /@types/multicast-dns@7.2.1: resolution: {integrity: sha512-A2PmB8MRcNVEkw6wzGT5rtBHqyHOVjiRMkJH+zpJKXipSi+GGkHg6JjNFApDiYK9WefJqkVG0taln1VMl4TGfw==} dependencies: @@ -3454,11 +2877,9 @@ packages: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: '@types/node': 18.16.8 - dev: true /@types/prettier@2.7.1: resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} - dev: true /@types/responselike@1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} @@ -3474,11 +2895,10 @@ packages: resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} dependencies: '@types/node': 18.16.8 - dev: true /@types/seedrandom@3.0.2: resolution: {integrity: sha512-YPLqEOo0/X8JU3rdiq+RgUKtQhQtrppE766y7vMTu8dGML7TVtZNiiiaC/hhU9Zqw9UYopXxhuWWENclMVBwKQ==} - dev: true + dev: false /@types/semver@7.5.0: resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} @@ -3502,7 +2922,7 @@ packages: '@types/yargs-parser': 21.0.0 dev: true - /@typescript-eslint/eslint-plugin@5.42.0(@typescript-eslint/parser@5.42.0)(eslint@8.26.0)(typescript@4.9.5): + /@typescript-eslint/eslint-plugin@5.42.0(@typescript-eslint/parser@5.42.0)(eslint@8.26.0)(typescript@5.1.6): resolution: {integrity: sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3513,23 +2933,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.42.0(eslint@8.26.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.42.0(eslint@8.26.0)(typescript@5.1.6) '@typescript-eslint/scope-manager': 5.42.0 - '@typescript-eslint/type-utils': 5.42.0(eslint@8.26.0)(typescript@4.9.5) - '@typescript-eslint/utils': 5.42.0(eslint@8.26.0)(typescript@4.9.5) + '@typescript-eslint/type-utils': 5.42.0(eslint@8.26.0)(typescript@5.1.6) + '@typescript-eslint/utils': 5.42.0(eslint@8.26.0)(typescript@5.1.6) debug: 4.3.4(supports-color@8.1.1) eslint: 8.26.0 ignore: 5.2.4 natural-compare-lite: 1.4.0 regexpp: 3.2.0 - semver: 7.5.0 - tsutils: 3.21.0(typescript@4.9.5) - typescript: 4.9.5 + semver: 7.5.1 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.42.0(eslint@8.26.0)(typescript@4.9.5): + /@typescript-eslint/parser@5.42.0(eslint@8.26.0)(typescript@5.1.6): resolution: {integrity: sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3541,10 +2961,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.42.0 '@typescript-eslint/types': 5.42.0 - '@typescript-eslint/typescript-estree': 5.42.0(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 5.42.0(typescript@5.1.6) debug: 4.3.4(supports-color@8.1.1) eslint: 8.26.0 - typescript: 4.9.5 + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true @@ -3557,7 +2977,7 @@ packages: '@typescript-eslint/visitor-keys': 5.42.0 dev: true - /@typescript-eslint/type-utils@5.42.0(eslint@8.26.0)(typescript@4.9.5): + /@typescript-eslint/type-utils@5.42.0(eslint@8.26.0)(typescript@5.1.6): resolution: {integrity: sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3567,12 +2987,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.42.0(typescript@4.9.5) - '@typescript-eslint/utils': 5.42.0(eslint@8.26.0)(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 5.42.0(typescript@5.1.6) + '@typescript-eslint/utils': 5.42.0(eslint@8.26.0)(typescript@5.1.6) debug: 4.3.4(supports-color@8.1.1) eslint: 8.26.0 - tsutils: 3.21.0(typescript@4.9.5) - typescript: 4.9.5 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true @@ -3582,7 +3002,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.42.0(typescript@4.9.5): + /@typescript-eslint/typescript-estree@5.42.0(typescript@5.1.6): resolution: {integrity: sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3597,13 +3017,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.0 - tsutils: 3.21.0(typescript@4.9.5) - typescript: 4.9.5 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.42.0(eslint@8.26.0)(typescript@4.9.5): + /@typescript-eslint/utils@5.42.0(eslint@8.26.0)(typescript@5.1.6): resolution: {integrity: sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -3613,7 +3033,7 @@ packages: '@types/semver': 7.5.0 '@typescript-eslint/scope-manager': 5.42.0 '@typescript-eslint/types': 5.42.0 - '@typescript-eslint/typescript-estree': 5.42.0(typescript@4.9.5) + '@typescript-eslint/typescript-estree': 5.42.0(typescript@5.1.6) eslint: 8.26.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.26.0) @@ -3635,19 +3055,19 @@ packages: resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} dev: true - /@zombienet/cli@1.3.52(@polkadot/util@12.2.1)(@types/node@18.16.8): - resolution: {integrity: sha512-KJo6w6m/tpNtVAgsz999BYTm+jyDLDKsunhMJJJX9AxCqGwGJnRd5Je4ep4u7p8pxbYNhfQoGwIGzt50lk1VkQ==} + /@zombienet/cli@1.3.63(@polkadot/util@12.3.2)(@types/node@18.16.8): + resolution: {integrity: sha512-0SiPqPU5Y3ucHwVUGthleUa5UBdEMOOGxuNvdKlxHEoundqm8NleXes8otgRnRNBLyCgpHZn9A6Fuh7fp+ZqFw==} engines: {node: '>=18'} hasBin: true dependencies: - '@zombienet/dsl-parser-wrapper': 0.1.7 - '@zombienet/orchestrator': 0.0.41(@polkadot/util@12.2.1)(@types/node@18.16.8) - '@zombienet/utils': 0.0.20(@types/node@18.16.8)(typescript@5.0.4) + '@zombienet/dsl-parser-wrapper': 0.1.10 + '@zombienet/orchestrator': 0.0.50(@polkadot/util@12.3.2)(@types/node@18.16.8) + '@zombienet/utils': 0.0.21(@types/node@18.16.8)(typescript@5.1.6) cli-progress: 3.12.0 - commander: 10.0.1 + commander: 11.0.0 debug: 4.3.4(supports-color@8.1.1) nunjucks: 3.2.4 - typescript: 5.0.4 + typescript: 5.1.6 transitivePeerDependencies: - '@polkadot/util' - '@swc/core' @@ -3660,32 +3080,33 @@ packages: - utf-8-validate dev: true - /@zombienet/dsl-parser-wrapper@0.1.7: - resolution: {integrity: sha512-pJqo1LZbNqnL6Of1h67eYtTTu0BLcf+U/nGQtj8pYr0V4XVDWdCYvT4C9kXkrh5964nKz3KGB7Eky43NqRJZqg==} + /@zombienet/dsl-parser-wrapper@0.1.10: + resolution: {integrity: sha512-2r2SjanMcNTQiiwTtj/TRO89ek4KoIKGKhgcdHm8+uXPVWuU3tIh/unN8+m51Jnm2jhCLkQQwa5aidvSC02wOg==} dev: true - /@zombienet/orchestrator@0.0.41(@polkadot/util@12.2.1)(@types/node@18.16.8): - resolution: {integrity: sha512-wfuE9oK1GYBA/UK9tBbtdRQQhJ9WCZpU9MML4uAN0+jn1knaocNyaB+Wk2xqWp5ACb7Wz+75kxYZ08yzerizHw==} + /@zombienet/orchestrator@0.0.50(@polkadot/util@12.3.2)(@types/node@18.16.8): + resolution: {integrity: sha512-phpyoUmC2Kv+IJ8naqvaJ/CIT0DT+WNpACa22LTdx4ZukJWXbVfTkWm1imejApUyk7NmLK92OlwCdUOGdyOATg==} + engines: {node: '>=18'} dependencies: - '@polkadot/api': 10.7.1 - '@polkadot/keyring': 12.1.2(@polkadot/util-crypto@12.2.1)(@polkadot/util@12.2.1) - '@polkadot/util-crypto': 12.2.1(@polkadot/util@12.2.1) - '@zombienet/utils': 0.0.20(@types/node@18.16.8)(typescript@5.0.4) + '@polkadot/api': 10.9.1 + '@polkadot/keyring': 12.3.2(@polkadot/util-crypto@12.3.2)(@polkadot/util@12.3.2) + '@polkadot/util-crypto': 12.3.2(@polkadot/util@12.3.2) + '@zombienet/utils': 0.0.21(@types/node@18.16.8)(typescript@5.1.6) JSONStream: 1.3.5 chai: 4.3.7 debug: 4.3.4(supports-color@8.1.1) execa: 5.1.1 fs-extra: 11.1.1 - jsdom: 22.0.0 + jsdom: 22.1.0 json-bigint: 1.0.0 libp2p-crypto: 0.21.2 - minimatch: 9.0.0 + minimatch: 9.0.3 mocha: 10.2.0 napi-maybe-compressed-blob: 0.0.11 peer-id: 0.16.0 tmp-promise: 3.0.3 - typescript: 5.0.4 - yaml: 2.2.2 + typescript: 5.1.6 + yaml: 2.3.1 transitivePeerDependencies: - '@polkadot/util' - '@swc/core' @@ -3698,15 +3119,15 @@ packages: - utf-8-validate dev: true - /@zombienet/utils@0.0.20(@types/node@18.16.8)(typescript@5.0.4): - resolution: {integrity: sha512-pW+iOVo49AYNuLnbXYlMCWQN/X1RadaF1gui1//qaF3B3eFe83n6DPq7qCKyEu3EoIoAvzEPubWGpxIBfKfGrw==} + /@zombienet/utils@0.0.21(@types/node@18.16.8)(typescript@5.1.6): + resolution: {integrity: sha512-31fMNlITzmj1gPha2CcihDE6nON94r8ixZTZbWa2g0nacS0nnoTKUNFukw9vg+aGF5QkwSevy+eobOQEb/jhjg==} dependencies: cli-table3: 0.6.3 debug: 4.3.4(supports-color@8.1.1) mocha: 10.2.0 nunjucks: 3.2.4 toml: 3.0.0 - ts-node: 10.9.1(@types/node@18.16.8)(typescript@5.0.4) + ts-node: 10.9.1(@types/node@18.16.8)(typescript@5.1.6) transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -3775,14 +3196,6 @@ packages: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} dev: true - /acorn-jsx@5.3.2(acorn@6.4.2): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 6.4.2 - dev: true - /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -3796,12 +3209,6 @@ packages: engines: {node: '>=0.4.0'} dev: true - /acorn@6.4.2: - resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} @@ -3859,15 +3266,6 @@ packages: uri-js: 4.4.1 dev: true - /ajv@8.11.0: - resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} - 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 - /ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} dependencies: @@ -3882,11 +3280,6 @@ packages: engines: {node: '>=6'} dev: true - /ansi-escapes@3.2.0: - resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} - engines: {node: '>=4'} - dev: true - /ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -3899,16 +3292,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ansi-regex@3.0.1: - resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} - engines: {node: '>=4'} - dev: true - - /ansi-regex@4.1.1: - resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} - engines: {node: '>=6'} - dev: true - /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -3919,28 +3302,12 @@ packages: engines: {node: '>=4'} dependencies: color-convert: 1.9.3 - dev: true /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: true - - /ansicolors@0.3.2: - resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} - dev: true - - /antlr4@4.7.1: - resolution: {integrity: sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ==} - dev: true - - /antlr4ts@0.5.0-dev: - resolution: {integrity: sha512-FXZRGC53ZejWLOMzxJ6IpgmGYNzBYeaoN5FBQe2Y6+iEA+JFNZz+J67TF84ajksmzVX8BUi+Ytx7oih+BWtA8A==} - dependencies: - source-map-support: 0.5.21 - dev: true /any-signal@3.0.1: resolution: {integrity: sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==} @@ -3999,12 +3366,6 @@ packages: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true @@ -4027,12 +3388,10 @@ packages: /array-back@3.1.0: resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} engines: {node: '>=6'} - dev: true /array-back@4.0.2: resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} engines: {node: '>=8'} - dev: true /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} @@ -4066,15 +3425,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - dev: true - - /astral-regex@1.0.0: - resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} - engines: {node: '>=4'} - dev: true - /async-each@1.0.6: resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} dev: true @@ -4087,11 +3437,6 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - dev: true - /atob@2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} @@ -4113,7 +3458,7 @@ packages: dependencies: archy: 1.0.0 debug: 4.3.4(supports-color@8.1.1) - fastq: 1.13.0 + fastq: 1.15.0 queue-microtask: 1.2.3 transitivePeerDependencies: - supports-color @@ -4132,7 +3477,7 @@ packages: /axios@1.1.2: resolution: {integrity: sha512-bznQyETwElsXl2RK7HLLwb5GPpOLlycxHCtrpDR/4RqqBzjARaOTo3jz4IgtntWUYee7Ne4S8UHd92VCuzPaWA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -4141,13 +3486,11 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true /base-x@3.0.9: resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} dependencies: safe-buffer: 5.2.1 - dev: true /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -4200,7 +3543,6 @@ packages: /bignumber.js@9.1.1: resolution: {integrity: sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==} - dev: true /binary-extensions@1.13.1: resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} @@ -4225,13 +3567,13 @@ packages: /bip39@3.1.0: resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==} dependencies: - '@noble/hashes': 1.3.0 + '@noble/hashes': 1.3.1 dev: true /bitfield@4.1.0: resolution: {integrity: sha512-6cEDG3K+PK9f+B7WyhWYjp09bqSa+uaAaecVA7Y5giFixyVe1s6HKGnvOqYNR4Mi4fBMjfDPLBpHkKvzzgP7kg==} engines: {node: '>=8'} - dev: true + dev: false /bl@1.2.3: resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} @@ -4250,7 +3592,6 @@ packages: /blakejs@1.2.1: resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - dev: true /bls-eth-wasm@0.4.8: resolution: {integrity: sha512-ye7+G6KFLb3i9xSrLASAoYqOUK5WLB6XA5DD8Sh0UQpZ3T999ylsYbFdoOJpmvTDuBuMi23Vy8Jm0pn/GF01CA==} @@ -4258,7 +3599,7 @@ packages: /bn.js@4.11.6: resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - dev: true + dev: false /bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} @@ -4271,7 +3612,6 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -4329,24 +3669,11 @@ packages: evp_bytestokey: 1.0.3 inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - - /browserslist@4.21.4: - resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001429 - electron-to-chromium: 1.4.284 - node-releases: 2.0.6 - update-browserslist-db: 1.0.10(browserslist@4.21.4) - dev: true /bs58@4.0.1: resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} dependencies: base-x: 3.0.9 - dev: true /bs58check@2.1.2: resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} @@ -4354,7 +3681,6 @@ packages: bs58: 4.0.1 create-hash: 1.2.0 safe-buffer: 5.2.1 - dev: true /buffer-alloc-unsafe@1.1.0: resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} @@ -4382,11 +3708,10 @@ packages: /buffer-reverse@1.0.1: resolution: {integrity: sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==} - dev: true + dev: false /buffer-xor@1.0.3: resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - dev: true /buffer-xor@2.0.2: resolution: {integrity: sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==} @@ -4513,25 +3838,6 @@ packages: get-intrinsic: 1.2.1 dev: true - /caller-callsite@2.0.0: - resolution: {integrity: sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==} - engines: {node: '>=4'} - dependencies: - callsites: 2.0.0 - dev: true - - /caller-path@2.0.0: - resolution: {integrity: sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==} - engines: {node: '>=4'} - dependencies: - caller-callsite: 2.0.0 - dev: true - - /callsites@2.0.0: - resolution: {integrity: sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==} - engines: {node: '>=4'} - dev: true - /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -4542,18 +3848,6 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001429: - resolution: {integrity: sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg==} - dev: true - - /cardinal@2.1.1: - resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} - hasBin: true - dependencies: - ansicolors: 0.3.2 - redeyed: 2.1.1 - dev: true - /case@1.6.3: resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} engines: {node: '>= 0.8.0'} @@ -4597,7 +3891,6 @@ packages: 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==} @@ -4605,7 +3898,6 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true /chalk@5.2.0: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} @@ -4685,7 +3977,6 @@ packages: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true /class-is@1.1.0: resolution: {integrity: sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==} @@ -4718,20 +4009,6 @@ packages: engines: {node: '>=6'} dev: true - /clean-stack@3.0.1: - resolution: {integrity: sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 4.0.0 - dev: true - - /cli-cursor@2.1.0: - resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} - engines: {node: '>=4'} - dependencies: - restore-cursor: 2.0.0 - dev: true - /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -4760,10 +4037,6 @@ packages: '@colors/colors': 1.5.0 dev: true - /cli-width@2.2.1: - resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==} - dev: true - /cli-width@4.0.0: resolution: {integrity: sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==} engines: {node: '>= 12'} @@ -4814,22 +4087,18 @@ packages: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 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'} 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.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true /color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} @@ -4864,10 +4133,6 @@ packages: delayed-stream: 1.0.0 dev: true - /command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - dev: true - /command-line-args@5.2.1: resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} engines: {node: '>=4.0.0'} @@ -4876,7 +4141,6 @@ packages: 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==} @@ -4886,19 +4150,10 @@ packages: 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@2.18.0: - resolution: {integrity: sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==} - dev: true - /commander@3.0.2: - resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} + /commander@11.0.0: + resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==} + engines: {node: '>=16'} dev: true /commander@5.1.0: @@ -4917,16 +4172,11 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true /console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: true - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true - /cookie@0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} @@ -4941,16 +4191,6 @@ packages: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true - /cosmiconfig@5.2.1: - resolution: {integrity: sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==} - engines: {node: '>=4'} - dependencies: - import-fresh: 2.0.0 - is-directory: 0.3.1 - js-yaml: 3.14.1 - parse-json: 4.0.0 - dev: true - /create-hash@1.2.0: resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} dependencies: @@ -4959,7 +4199,6 @@ packages: md5.js: 1.3.5 ripemd160: 2.0.2 sha.js: 2.4.11 - dev: true /create-hmac@1.1.7: resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} @@ -4970,7 +4209,6 @@ packages: ripemd160: 2.0.2 safe-buffer: 5.2.1 sha.js: 2.4.11 - dev: true /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -4984,17 +4222,6 @@ packages: - encoding dev: true - /cross-spawn@6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} - engines: {node: '>=4.8'} - 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: true - /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -5006,7 +4233,7 @@ packages: /crypto-js@3.3.0: resolution: {integrity: sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==} - dev: true + dev: false /cssstyle@3.0.0: resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} @@ -5149,17 +4376,11 @@ packages: /deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} - dev: true /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true - /deepmerge@4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} - engines: {node: '>=0.10.0'} - dev: true - /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -5301,18 +4522,6 @@ packages: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} dev: true - /ejs@3.1.8: - resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.8.5 - dev: true - - /electron-to-chromium@1.4.284: - resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} - dev: true - /elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} dependencies: @@ -5324,14 +4533,6 @@ packages: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - /emoji-regex@10.2.1: - resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==} - dev: true - - /emoji-regex@7.0.3: - resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} - dev: true - /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true @@ -5372,46 +4573,10 @@ packages: resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} dev: true - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - /es6-object-assign@1.1.0: resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==} dev: true - /esbuild@0.17.4: - resolution: {integrity: sha512-zBn9MeCwT7W5F1a3lXClD61ip6vQM+H8Msb0w8zMT4ZKBpDg+rFAraNyWCDelB/2L6M3g6AXHPnsyvjMFnxtFw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.17.4 - '@esbuild/android-arm64': 0.17.4 - '@esbuild/android-x64': 0.17.4 - '@esbuild/darwin-arm64': 0.17.4 - '@esbuild/darwin-x64': 0.17.4 - '@esbuild/freebsd-arm64': 0.17.4 - '@esbuild/freebsd-x64': 0.17.4 - '@esbuild/linux-arm': 0.17.4 - '@esbuild/linux-arm64': 0.17.4 - '@esbuild/linux-ia32': 0.17.4 - '@esbuild/linux-loong64': 0.17.4 - '@esbuild/linux-mips64el': 0.17.4 - '@esbuild/linux-ppc64': 0.17.4 - '@esbuild/linux-riscv64': 0.17.4 - '@esbuild/linux-s390x': 0.17.4 - '@esbuild/linux-x64': 0.17.4 - '@esbuild/netbsd-x64': 0.17.4 - '@esbuild/openbsd-x64': 0.17.4 - '@esbuild/sunos-x64': 0.17.4 - '@esbuild/win32-arm64': 0.17.4 - '@esbuild/win32-ia32': 0.17.4 - '@esbuild/win32-x64': 0.17.4 - dev: true - /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -5420,7 +4585,6 @@ packages: /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - dev: true /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} @@ -5441,14 +4605,6 @@ packages: eslint: 8.26.0 dev: true - /eslint-scope@4.0.3: - resolution: {integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==} - engines: {node: '>=4.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - /eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -5465,13 +4621,6 @@ packages: estraverse: 5.3.0 dev: true - /eslint-utils@1.4.3: - resolution: {integrity: sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==} - engines: {node: '>=6'} - dependencies: - eslint-visitor-keys: 1.3.0 - dev: true - /eslint-utils@3.0.0(eslint@8.26.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} @@ -5482,11 +4631,6 @@ packages: eslint-visitor-keys: 2.1.0 dev: true - /eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - dev: true - /eslint-visitor-keys@2.1.0: resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} engines: {node: '>=10'} @@ -5497,51 +4641,6 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@5.16.0: - resolution: {integrity: sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==} - engines: {node: ^6.14.0 || ^8.10.0 || >=9.10.0} - hasBin: true - dependencies: - '@babel/code-frame': 7.18.6 - ajv: 6.12.6 - chalk: 2.4.2 - cross-spawn: 6.0.5 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 - eslint-scope: 4.0.3 - eslint-utils: 1.4.3 - eslint-visitor-keys: 1.3.0 - espree: 5.0.1 - esquery: 1.5.0 - esutils: 2.0.3 - file-entry-cache: 5.0.1 - functional-red-black-tree: 1.0.1 - glob: 7.2.3 - globals: 11.12.0 - ignore: 4.0.6 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - inquirer: 6.5.2 - js-yaml: 3.14.1 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.3.0 - lodash: 4.17.21 - minimatch: 3.1.2 - mkdirp: 0.5.6 - natural-compare: 1.4.0 - optionator: 0.8.3 - path-is-inside: 1.0.2 - progress: 2.0.3 - regexpp: 2.0.1 - semver: 5.7.1 - strip-ansi: 4.0.0 - strip-json-comments: 2.0.1 - table: 5.4.6 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - /eslint@8.26.0: resolution: {integrity: sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5595,15 +4694,6 @@ packages: engines: {node: '>=6'} dev: true - /espree@5.0.1: - resolution: {integrity: sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==} - engines: {node: '>=6.0.0'} - dependencies: - acorn: 6.4.2 - acorn-jsx: 5.3.2(acorn@6.4.2) - eslint-visitor-keys: 1.3.0 - dev: true - /espree@9.5.2: resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5613,12 +4703,6 @@ packages: eslint-visitor-keys: 3.4.1 dev: true - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} @@ -5652,7 +4736,7 @@ packages: resolution: {integrity: sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==} dependencies: js-sha3: 0.8.0 - dev: true + dev: false /ethereum-cryptography@0.1.3: resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} @@ -5672,14 +4756,13 @@ packages: scrypt-js: 3.0.1 secp256k1: 4.0.3 setimmediate: 1.0.5 - dev: true /ethereumjs-abi@0.6.8: resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} dependencies: bn.js: 4.12.0 ethereumjs-util: 6.2.1 - dev: true + dev: false /ethereumjs-util@6.2.1: resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} @@ -5691,7 +4774,7 @@ packages: ethereum-cryptography: 0.1.3 ethjs-util: 0.1.6 rlp: 2.2.7 - dev: true + dev: false /ethereumjs-util@7.1.5: resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} @@ -5702,7 +4785,7 @@ packages: create-hash: 1.2.0 ethereum-cryptography: 0.1.3 rlp: 2.2.7 - dev: true + dev: false /ethers@5.7.2: resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} @@ -5747,7 +4830,7 @@ packages: dependencies: bn.js: 4.11.6 number-to-bn: 1.7.0 - dev: true + dev: false /ethjs-util@0.1.6: resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} @@ -5755,7 +4838,7 @@ packages: dependencies: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 - dev: true + dev: false /event-iterator@2.0.0: resolution: {integrity: sha512-KGft0ldl31BZVV//jj+IAIGCxkvvUkkON+ScH6zfoX+l+omX6001ggyRSpI0Io2Hlro0ThXotswCtfzS8UkIiQ==} @@ -5792,7 +4875,6 @@ packages: dependencies: md5.js: 1.3.5 safe-buffer: 5.2.1 - dev: true /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} @@ -5888,10 +4970,6 @@ packages: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true - /fast-diff@1.2.0: - resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - dev: true - /fast-fifo@1.2.0: resolution: {integrity: sha512-NcvQXt7Cky1cNau15FWy64IjuO8X0JijhTBBrJj1YlxlDfRkJXNaK9RFUjwpfDPzMdv7wB38jr53l9tkNLxnWg==} dev: true @@ -5916,7 +4994,7 @@ packages: engines: {node: '>= 10.0.0'} dependencies: ajv: 6.12.6 - deepmerge: 4.2.2 + deepmerge: 4.3.1 rfdc: 1.3.0 string-similarity: 4.0.4 dev: true @@ -5942,11 +5020,6 @@ packages: fast-decode-uri-component: 1.0.1 dev: true - /fast-redact@3.1.2: - resolution: {integrity: sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==} - engines: {node: '>=6'} - dev: true - /fast-redact@3.2.0: resolution: {integrity: sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==} engines: {node: '>=6'} @@ -5988,10 +5061,10 @@ packages: flatstr: 1.0.12 light-my-request: 4.12.0 pino: 6.14.0 - readable-stream: 3.6.0 + readable-stream: 3.6.2 rfdc: 1.3.0 - secure-json-parse: 2.5.0 - semver: 7.5.0 + secure-json-parse: 2.7.0 + semver: 7.5.1 tiny-lru: 7.0.6 transitivePeerDependencies: - supports-color @@ -6043,13 +5116,6 @@ packages: node-domexception: 1.0.0 web-streams-polyfill: 3.2.1 - /figures@2.0.0: - resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - /figures@5.0.0: resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} engines: {node: '>=14'} @@ -6058,13 +5124,6 @@ packages: is-unicode-supported: 1.3.0 dev: true - /file-entry-cache@5.0.1: - resolution: {integrity: sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==} - engines: {node: '>=4'} - dependencies: - flat-cache: 2.0.1 - dev: true - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -6082,12 +5141,6 @@ packages: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} dev: true - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.0 - dev: true - /fill-range@4.0.0: resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} engines: {node: '>=0.10.0'} @@ -6105,13 +5158,6 @@ packages: to-regex-range: 5.0.1 dev: true - /find-config@1.0.0: - resolution: {integrity: sha512-Z+suHH+7LSE40WfUeZPIxSxypCWvrzdVc60xAjUShZeT5eMWM0/FQUduq3HjluyfAHWvC/aOBkT1pTZktyF/jg==} - engines: {node: '>= 0.12'} - dependencies: - user-home: 2.0.0 - dev: true - /find-my-way@4.5.1: resolution: {integrity: sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg==} engines: {node: '>=10'} @@ -6136,7 +5182,6 @@ packages: engines: {node: '>=4.0.0'} dependencies: array-back: 3.1.0 - dev: true /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} @@ -6154,15 +5199,6 @@ packages: path-exists: 5.0.0 dev: true - /flat-cache@2.0.1: - resolution: {integrity: sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==} - engines: {node: '>=4'} - dependencies: - flatted: 2.0.2 - rimraf: 2.6.3 - write: 1.0.3 - dev: true - /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -6180,10 +5216,6 @@ packages: resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==} dev: true - /flatted@2.0.2: - resolution: {integrity: sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==} - dev: true - /flatted@3.2.7: resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} dev: true @@ -6202,18 +5234,6 @@ packages: optional: true dev: true - /follow-redirects@1.15.2(debug@4.3.4): - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: - debug: 4.3.4(supports-color@8.1.1) - dev: true - /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -6266,21 +5286,11 @@ packages: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: true - /fs-extra@0.30.0: - resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} - 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@11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} engines: {node: '>=14.14'} dependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.0 dev: true @@ -6297,29 +5307,9 @@ packages: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} dependencies: - graceful-fs: 4.2.10 - 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'} - dependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jsonfile: 4.0.0 universalify: 0.1.2 - dev: true - - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: true /fs-minipass@1.2.7: resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==} @@ -6336,7 +5326,6 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true /fsevents@1.2.13: resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} @@ -6362,10 +5351,6 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true - /functional-red-black-tree@1.0.1: - resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} - dev: true - /gauge@2.7.4: resolution: {integrity: sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==} dependencies: @@ -6406,11 +5391,6 @@ packages: bundledDependencies: - node-pre-gyp - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -6437,11 +5417,6 @@ packages: resolution: {integrity: sha512-BDJawD5PU2gZv6Vlp8O28H4GnZcsr3h9gZUvnAP5xXP3WOy/QAoOsyMepSkw21jur+4t5Vppde72ChjhTIzxzg==} dev: true - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - /get-stream@4.1.0: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} engines: {node: '>=6'} @@ -6511,7 +5486,6 @@ 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==} @@ -6545,11 +5519,6 @@ packages: path-scurry: 1.9.2 dev: true - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - /globals@13.20.0: resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} engines: {node: '>=8'} @@ -6618,7 +5587,6 @@ packages: /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true /grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} @@ -6629,23 +5597,9 @@ packages: engines: {node: '>=4.x'} dev: true - /handlebars@4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.7 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: true - /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} - dev: true /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -6721,9 +5675,8 @@ packages: engines: {node: '>=4'} dependencies: inherits: 2.0.4 - readable-stream: 3.6.0 + readable-stream: 3.6.2 safe-buffer: 5.2.1 - dev: true /hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -6820,17 +5773,6 @@ packages: ms: 2.1.3 dev: true - /husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /hyperlinker@1.0.0: - resolution: {integrity: sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==} - engines: {node: '>=4'} - dev: true - /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -6855,24 +5797,11 @@ packages: minimatch: 3.1.2 dev: true - /ignore@4.0.6: - resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} - engines: {node: '>= 4'} - dev: true - /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} dev: true - /import-fresh@2.0.0: - resolution: {integrity: sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==} - engines: {node: '>=4'} - dependencies: - caller-path: 2.0.0 - resolve-from: 3.0.0 - dev: true - /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -6900,7 +5829,6 @@ packages: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -6909,25 +5837,6 @@ packages: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true - /inquirer@6.5.2: - resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==} - engines: {node: '>=6.0.0'} - dependencies: - ansi-escapes: 3.2.0 - chalk: 2.4.2 - cli-cursor: 2.1.0 - cli-width: 2.2.1 - external-editor: 3.1.0 - figures: 2.0.0 - lodash: 4.17.21 - mute-stream: 0.0.7 - run-async: 2.4.1 - rxjs: 6.6.7 - string-width: 2.1.1 - strip-ansi: 5.2.0 - through: 2.3.8 - dev: true - /inquirer@9.2.5: resolution: {integrity: sha512-Vy3qZFUPKILCgfeg6eEfKSlv4QbwwfGmdoAYqXYGlPEhY4HH0jQv+ynHkEYYE4eBDCDMWKHs77ByfHcy1GyDfA==} engines: {node: '>=14.18.0'} @@ -7018,10 +5927,6 @@ packages: has-tostringtag: 1.0.0 dev: true - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - /is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} dev: true @@ -7086,17 +5991,6 @@ packages: kind-of: 6.0.3 dev: true - /is-directory@0.3.1: - resolution: {integrity: sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==} - engines: {node: '>=0.10.0'} - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - /is-electron@2.2.2: resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} dev: true @@ -7125,11 +6019,6 @@ packages: number-is-nan: 1.0.1 dev: true - /is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - dev: true - /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -7159,7 +6048,7 @@ packages: /is-hex-prefixed@1.0.0: resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} engines: {node: '>=6.5.0', npm: '>=3'} - dev: true + dev: false /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} @@ -7251,13 +6140,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: true @@ -7278,7 +6160,7 @@ packages: engines: {node: '>=10'} dependencies: events: 3.3.0 - readable-stream: 3.6.0 + readable-stream: 3.6.2 dev: true /isobject@2.1.0: @@ -7475,17 +6357,6 @@ packages: engines: {node: '>=16.0.0', npm: '>=7.0.0'} dev: true - /jake@10.8.5: - resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.4 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - /js-sdsl@4.4.0: resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==} dev: true @@ -7493,18 +6364,6 @@ packages: /js-sha3@0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - /js-yaml@4.0.0: resolution: {integrity: sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==} hasBin: true @@ -7523,8 +6382,8 @@ packages: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} dev: true - /jsdom@22.0.0: - resolution: {integrity: sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==} + /jsdom@22.1.0: + resolution: {integrity: sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==} engines: {node: '>=16'} peerDependencies: canvas: ^2.5.0 @@ -7561,12 +6420,6 @@ packages: - utf-8-validate dev: true - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - /json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} dependencies: @@ -7581,10 +6434,6 @@ packages: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true - /json-parse-better-errors@1.0.2: - resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} - dev: true - /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -7606,12 +6455,6 @@ packages: hasBin: true dev: true - /jsonfile@2.4.0: - resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - /jsonfile@3.0.1: resolution: {integrity: sha512-oBko6ZHlubVB5mRFkur5vgYR1UyqX+S6Y/oCfLhqNdcc2fYFlDpIoNc7AfKS1KOGcnNAkvsr0grLck9ANM815w==} optionalDependencies: @@ -7622,7 +6465,6 @@ packages: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: graceful-fs: 4.2.11 - dev: true /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -7648,9 +6490,8 @@ packages: requiresBuild: true dependencies: node-addon-api: 2.0.2 - node-gyp-build: 4.5.0 - readable-stream: 3.6.0 - dev: true + node-gyp-build: 4.6.0 + readable-stream: 3.6.2 /keyv@3.1.0: resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==} @@ -7688,12 +6529,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /klaw@1.3.1: - resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - /kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} dev: true @@ -7726,14 +6561,6 @@ packages: classic-level: 1.3.0 dev: true - /levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - dev: true - /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -7746,7 +6573,7 @@ packages: resolution: {integrity: sha512-EXFrhSpiHtJ+/L8xXDvQNK5VjUMG51u878jzZcaT5XhuN/zFg6PWJFnl/qB2Y2j7eMWnvCRP7Kp+ua2H36cG4g==} engines: {node: '>=12.0.0'} dependencies: - '@noble/ed25519': 1.7.1 + '@noble/ed25519': 1.7.3 '@noble/secp256k1': 1.7.1 err-code: 3.0.1 iso-random-stream: 2.0.2 @@ -7835,10 +6662,10 @@ packages: /light-my-request@4.12.0: resolution: {integrity: sha512-0y+9VIfJEsPVzK5ArSIJ8Dkxp8QMP7/aCuxCUtG/tr9a2NoOf/snATE/OUc05XUplJCEnRh6gTkH7xh9POt1DQ==} dependencies: - ajv: 8.11.0 + ajv: 8.12.0 cookie: 0.5.0 process-warning: 1.0.0 - set-cookie-parser: 2.5.1 + set-cookie-parser: 2.6.0 dev: true /light-my-request@5.9.1: @@ -7876,7 +6703,6 @@ packages: /lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: true /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -8007,12 +6833,6 @@ packages: hash-base: 3.1.0 inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - - /memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - dev: true /merge-options@3.0.4: resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==} @@ -8039,7 +6859,7 @@ packages: crypto-js: 3.3.0 treeify: 1.1.0 web3-utils: 1.8.2 - dev: true + dev: false /micromatch@3.1.10: resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} @@ -8082,11 +6902,6 @@ packages: mime-db: 1.52.0 dev: true - /mimic-fn@1.2.0: - resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} - engines: {node: '>=4'} - dev: true - /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -8118,7 +6933,6 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: true /minimatch@5.0.1: resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} @@ -8127,13 +6941,6 @@ packages: brace-expansion: 2.0.1 dev: true - /minimatch@5.1.0: - resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@8.0.4: resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} engines: {node: '>=16 || 14 >=14.17'} @@ -8141,8 +6948,8 @@ packages: brace-expansion: 2.0.1 dev: true - /minimatch@9.0.0: - resolution: {integrity: sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==} + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 @@ -8254,14 +7061,13 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true dependencies: - minimist: 1.2.7 + minimist: 1.2.8 dev: true /mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true - dev: true /mnemonist@0.39.5: resolution: {integrity: sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==} @@ -8269,34 +7075,6 @@ packages: obliterator: 2.0.4 dev: true - /mocha@10.1.0: - resolution: {integrity: sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==} - engines: {node: '>= 14.0.0'} - hasBin: true - dependencies: - ansi-colors: 4.1.1 - browser-stdout: 1.3.1 - chokidar: 3.5.3 - debug: 4.3.4(supports-color@8.1.1) - diff: 5.0.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 7.2.0 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 5.0.1 - ms: 2.1.3 - nanoid: 3.3.3 - serialize-javascript: 6.0.0 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - workerpool: 6.2.1 - yargs: 16.2.0 - yargs-parser: 20.2.4 - yargs-unparser: 2.0.0 - dev: true - /mocha@10.2.0: resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} engines: {node: '>= 14.0.0'} @@ -8408,10 +7186,6 @@ packages: resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} dev: true - /mute-stream@0.0.7: - resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==} - dev: true - /mute-stream@1.0.0: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -8528,10 +7302,6 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /natural-orderby@2.0.3: - resolution: {integrity: sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==} - dev: true - /needle@2.9.1: resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} engines: {node: '>= 4.4.x'} @@ -8549,19 +7319,11 @@ packages: engines: {node: '>= 0.6'} dev: true - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - /netmask@2.0.2: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} dev: true - /nice-try@1.0.5: - resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} - dev: true - /nock@13.3.1: resolution: {integrity: sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==} engines: {node: '>= 10.13'} @@ -8581,7 +7343,6 @@ packages: /node-addon-api@2.0.2: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - dev: true /node-addon-api@5.1.0: resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} @@ -8616,15 +7377,9 @@ packages: engines: {node: '>= 6.13.0'} dev: true - /node-gyp-build@4.5.0: - resolution: {integrity: sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==} - hasBin: true - dev: true - /node-gyp-build@4.6.0: resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==} hasBin: true - dev: true /node-gyp@8.4.1: resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} @@ -8665,10 +7420,6 @@ packages: - supports-color dev: true - /node-releases@2.0.6: - resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} - dev: true - /noop-logger@0.1.1: resolution: {integrity: sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ==} dev: true @@ -8766,7 +7517,7 @@ packages: dependencies: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - dev: true + dev: false /nunjucks@3.2.4: resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==} @@ -8823,11 +7574,6 @@ packages: engines: {node: '>= 0.4'} dev: true - /object-treeify@1.1.33: - resolution: {integrity: sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==} - engines: {node: '>= 10'} - dev: true - /object-visit@1.0.1: resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} engines: {node: '>=0.10.0'} @@ -8863,7 +7609,6 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: true /one-time@1.0.0: resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} @@ -8871,13 +7616,6 @@ packages: fn.name: 1.1.0 dev: true - /onetime@2.0.1: - resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} - engines: {node: '>=4'} - dependencies: - mimic-fn: 1.2.0 - dev: true - /onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -8889,18 +7627,6 @@ packages: resolution: {integrity: sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==} dev: true - /optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - dev: true - /optionator@0.9.1: resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} engines: {node: '>= 0.8.0'} @@ -9061,18 +7787,10 @@ packages: optional: true /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@4.0.0: - resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} - engines: {node: '>=4'} + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} dependencies: - error-ex: 1.3.2 - json-parse-better-errors: 1.0.2 + callsites: 3.1.0 dev: true /parse-passwd@1.0.0: @@ -9091,13 +7809,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /password-prompt@1.1.2: - resolution: {integrity: sha512-bpuBhROdrhuN3E7G/koAju0WjVw9/uQOG5Co5mokNj0MiOSBVZS1JTwM4zl55hu0WFmIEFvO9cU9sJQiBIYeIA==} - dependencies: - ansi-escapes: 3.2.0 - cross-spawn: 6.0.5 - dev: true - /path-dirname@1.0.2: resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} dev: true @@ -9115,16 +7826,6 @@ packages: /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: true - - /path-is-inside@1.0.2: - resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==} - dev: true - - /path-key@2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - dev: true /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} @@ -9157,7 +7858,6 @@ packages: ripemd160: 2.0.2 safe-buffer: 5.2.1 sha.js: 2.4.11 - dev: true /peer-id@0.16.0: resolution: {integrity: sha512-EmL7FurFUduU9m1PS9cfJ5TAuCvxKQ7DKpfx3Yj6IKWyBRtosriFuOag/l3ni/dtPgPLwiA4R9IvpL7hsDLJuQ==} @@ -9170,10 +7870,6 @@ packages: uint8arrays: 3.1.1 dev: true - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -9198,7 +7894,7 @@ packages: resolution: {integrity: sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==} hasBin: true dependencies: - fast-redact: 3.1.2 + fast-redact: 3.2.0 fast-safe-stringify: 2.1.1 flatstr: 1.0.12 pino-std-serializers: 3.2.0 @@ -9256,11 +7952,6 @@ packages: which-pm-runs: 1.1.0 dev: true - /prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: true - /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -9271,34 +7962,10 @@ packages: engines: {node: '>=4'} dev: true - /prettier-plugin-solidity@1.0.0(prettier@2.7.1): - resolution: {integrity: sha512-gRJCeZ7imbWtNYN2SudjJoPmka5r6jcd2cSTV6FC3pVCtY6LFZbeQQjpKufUEp88hXBAAnkOTOh7TA5xwj9M3A==} - engines: {node: '>=12'} - peerDependencies: - prettier: ^2.3.0 - dependencies: - '@solidity-parser/parser': 0.14.5 - emoji-regex: 10.2.1 - escape-string-regexp: 4.0.0 - prettier: 2.7.1 - semver: 7.5.0 - solidity-comments-extractor: 0.0.7 - string-width: 4.2.3 - dev: true - - /prettier@1.19.1: - resolution: {integrity: sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==} - engines: {node: '>=4'} - hasBin: true - requiresBuild: true - dev: true - optional: true - /prettier@2.7.1: resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} engines: {node: '>=10.13.0'} hasBin: true - dev: true /private-ip@3.0.0: resolution: {integrity: sha512-HkMBs4nMtrP+cvcw0bDi2BAZIGgiKI4Zq8Oc+dMqNBpHS8iGL4+WO/pRtc8Bwnv9rjnV0QwMDwEBymFtqv7Kww==} @@ -9327,11 +7994,6 @@ packages: engines: {node: '>= 0.6.0'} dev: true - /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: true - /prom-client@14.2.0: resolution: {integrity: sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==} engines: {node: '>=10'} @@ -9503,7 +8165,6 @@ packages: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: safe-buffer: 5.2.1 - dev: true /rate-limiter-flexible@2.4.1: resolution: {integrity: sha512-dgH4T44TzKVO9CLArNto62hJOwlWJMLUjVVr/ii0uUzZXEXthDNr7/yefW5z/1vvHAfycc1tnuiYyNJ8CTRB3g==} @@ -9519,18 +8180,6 @@ packages: strip-json-comments: 2.0.1 dev: true - /readable-stream@2.3.7: - resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - /readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} dependencies: @@ -9543,15 +8192,6 @@ packages: util-deprecate: 1.0.2 dev: true - /readable-stream@3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -9559,7 +8199,6 @@ packages: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true /readable-stream@4.4.0: resolution: {integrity: sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==} @@ -9577,7 +8216,7 @@ packages: dependencies: graceful-fs: 4.2.11 micromatch: 3.1.10 - readable-stream: 2.3.7 + readable-stream: 2.3.8 transitivePeerDependencies: - supports-color dev: true @@ -9607,16 +8246,9 @@ packages: ms: 2.1.3 dev: true - /redeyed@2.1.1: - resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} - dependencies: - esprima: 4.0.1 - dev: true - /reduce-flatten@2.0.0: resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} engines: {node: '>=6'} - dev: true /regex-not@1.0.2: resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} @@ -9626,11 +8258,6 @@ packages: safe-regex: 1.1.0 dev: true - /regexpp@2.0.1: - resolution: {integrity: sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==} - engines: {node: '>=6.5.0'} - dev: true - /regexpp@3.2.0: resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} engines: {node: '>=8'} @@ -9682,11 +8309,6 @@ packages: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} dev: true - /resolve-from@3.0.0: - resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} - engines: {node: '>=4'} - dev: true - /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -9716,14 +8338,6 @@ packages: lowercase-keys: 3.0.0 dev: true - /restore-cursor@2.0.0: - resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} - engines: {node: '>=4'} - dependencies: - onetime: 2.0.1 - signal-exit: 3.0.7 - dev: true - /restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -9765,13 +8379,6 @@ packages: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} dev: true - /rimraf@2.6.3: - resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - /rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true @@ -9799,24 +8406,17 @@ packages: dependencies: hash-base: 3.1.0 inherits: 2.0.4 - dev: true /rlp@2.2.7: resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} hasBin: true dependencies: bn.js: 5.2.1 - dev: true /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true - /run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - dev: true - /run-async@3.0.0: resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} engines: {node: '>=0.12.0'} @@ -9834,17 +8434,10 @@ packages: queue-microtask: 1.2.3 dev: true - /rxjs@6.6.7: - resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} - engines: {npm: '>=2.0.0'} - dependencies: - tslib: 1.14.1 - dev: true - /rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: - tslib: 2.5.0 + tslib: 2.6.1 /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -9852,7 +8445,6 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true /safe-regex2@2.0.0: resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} @@ -9902,12 +8494,7 @@ packages: dependencies: elliptic: 6.5.4 node-addon-api: 2.0.2 - node-gyp-build: 4.5.0 - dev: true - - /secure-json-parse@2.5.0: - resolution: {integrity: sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w==} - dev: true + node-gyp-build: 4.6.0 /secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} @@ -9915,7 +8502,7 @@ packages: /seedrandom@3.0.5: resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} - dev: true + dev: false /semver-store@0.3.0: resolution: {integrity: sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==} @@ -9963,10 +8550,6 @@ packages: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true - /set-cookie-parser@2.5.1: - resolution: {integrity: sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==} - dev: true - /set-cookie-parser@2.6.0: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} dev: true @@ -9987,7 +8570,6 @@ packages: /setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: true /sha.js@2.4.11: resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} @@ -9995,14 +8577,6 @@ packages: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - dev: true - - /shebang-command@1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: true /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} @@ -10011,11 +8585,6 @@ packages: shebang-regex: 3.0.0 dev: true - /shebang-regex@1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: true - /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} @@ -10056,15 +8625,6 @@ packages: engines: {node: '>=8'} dev: true - /slice-ansi@2.1.0: - resolution: {integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==} - engines: {node: '>=6'} - dependencies: - ansi-styles: 3.2.1 - astral-regex: 1.0.0 - is-fullwidth-code-point: 2.0.0 - dev: true - /smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -10144,87 +8704,6 @@ packages: smart-buffer: 4.2.0 dev: true - /solc@0.6.12: - resolution: {integrity: sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g==} - engines: {node: '>=8.0.0'} - hasBin: true - dependencies: - command-exists: 1.2.9 - commander: 3.0.2 - fs-extra: 0.30.0 - js-sha3: 0.8.0 - memorystream: 0.3.1 - require-from-string: 2.0.2 - semver: 5.7.1 - tmp: 0.0.33 - dev: true - - /solc@0.7.6: - resolution: {integrity: sha512-WsR/W7CXwh2VnmZapB4JrsDeLlshoKBz5Pz/zYNulB6LBsOEHI2Zj/GeKLMFcvv57OHiXHvxq5ZOQB+EdqxlxQ==} - engines: {node: '>=8.0.0'} - hasBin: true - dependencies: - command-exists: 1.2.9 - commander: 3.0.2 - follow-redirects: 1.15.2 - fs-extra: 0.30.0 - js-sha3: 0.8.0 - memorystream: 0.3.1 - require-from-string: 2.0.2 - semver: 5.7.1 - tmp: 0.0.33 - transitivePeerDependencies: - - debug - dev: true - - /solhint@3.3.7: - resolution: {integrity: sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ==} - hasBin: true - dependencies: - '@solidity-parser/parser': 0.14.5 - ajv: 6.12.6 - antlr4: 4.7.1 - ast-parents: 0.0.1 - chalk: 2.4.2 - commander: 2.18.0 - cosmiconfig: 5.2.1 - eslint: 5.16.0 - fast-diff: 1.2.0 - glob: 7.2.3 - ignore: 4.0.6 - js-yaml: 3.14.1 - lodash: 4.17.21 - semver: 6.3.0 - optionalDependencies: - prettier: 1.19.1 - transitivePeerDependencies: - - supports-color - dev: true - - /solidity-comments-extractor@0.0.7: - resolution: {integrity: sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==} - dev: true - - /solidity-docgen@0.5.17: - resolution: {integrity: sha512-RX5SPLFL9z0ZVBcZ/o5l/TKXMgSjNhWdumLuuv+Dy1O/66sThpHYd0HVpzdwAjVff0Ajk76bYM2zZYiMnqBfng==} - hasBin: true - dependencies: - '@oclif/command': 1.8.19(@oclif/config@1.18.5) - '@oclif/config': 1.18.5 - '@oclif/errors': 1.3.6 - '@oclif/plugin-help': 5.1.17 - globby: 11.1.0 - handlebars: 4.7.7 - json5: 2.2.3 - lodash: 4.17.21 - micromatch: 4.0.5 - minimatch: 5.1.0 - semver: 7.5.0 - solc: 0.6.12 - transitivePeerDependencies: - - supports-color - dev: true - /sonic-boom@1.4.1: resolution: {integrity: sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==} dependencies: @@ -10283,10 +8762,6 @@ packages: engines: {node: '>= 10.x'} dev: true - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - /sprintf-js@1.1.2: resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} dev: true @@ -10327,7 +8802,6 @@ packages: /string-format@2.0.0: resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} - dev: true /string-similarity@4.0.4: resolution: {integrity: sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==} @@ -10343,23 +8817,6 @@ packages: strip-ansi: 3.0.1 dev: true - /string-width@2.1.1: - resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} - engines: {node: '>=4'} - dependencies: - is-fullwidth-code-point: 2.0.0 - strip-ansi: 4.0.0 - dev: true - - /string-width@3.1.0: - resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} - engines: {node: '>=6'} - dependencies: - emoji-regex: 7.0.3 - is-fullwidth-code-point: 2.0.0 - strip-ansi: 5.2.0 - dev: true - /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -10379,7 +8836,6 @@ packages: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 - dev: true /strip-ansi@3.0.1: resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} @@ -10388,20 +8844,6 @@ packages: ansi-regex: 2.1.1 dev: true - /strip-ansi@4.0.0: - resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} - engines: {node: '>=4'} - dependencies: - ansi-regex: 3.0.1 - dev: true - - /strip-ansi@5.2.0: - resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} - engines: {node: '>=6'} - dependencies: - ansi-regex: 4.1.1 - dev: true - /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -10424,7 +8866,7 @@ packages: engines: {node: '>=6.5.0', npm: '>=3'} dependencies: is-hex-prefixed: 1.0.0 - dev: true + dev: false /strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} @@ -10441,14 +8883,12 @@ packages: engines: {node: '>=4'} dependencies: has-flag: 3.0.0 - dev: true /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - dev: true /supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} @@ -10456,14 +8896,6 @@ packages: dependencies: has-flag: 4.0.0 - /supports-hyperlinks@2.3.0: - resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - dev: true - /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true @@ -10483,17 +8915,6 @@ packages: deep-extend: 0.6.0 typical: 5.2.0 wordwrapjs: 4.0.1 - dev: true - - /table@5.4.6: - resolution: {integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==} - engines: {node: '>=6.0.0'} - dependencies: - ajv: 6.12.6 - lodash: 4.17.21 - slice-ansi: 2.1.0 - string-width: 3.1.0 - dev: true /tar-fs@1.16.3: resolution: {integrity: sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==} @@ -10548,14 +8969,6 @@ packages: bintrees: 1.0.2 dev: true - /temp@0.9.4: - resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} - engines: {node: '>=6.0.0'} - dependencies: - mkdirp: 0.5.6 - rimraf: 2.6.3 - dev: true - /text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} dev: true @@ -10626,11 +9039,6 @@ packages: resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} dev: true - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - /to-object-path@0.3.0: resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} engines: {node: '>=0.10.0'} @@ -10696,7 +9104,7 @@ packages: /treeify@1.1.0: resolution: {integrity: sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==} engines: {node: '>=0.6'} - dev: true + dev: false /triple-beam@1.3.0: resolution: {integrity: sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==} @@ -10716,15 +9124,13 @@ packages: 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@4.9.5): + /ts-essentials@7.0.3(typescript@5.1.6): resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} peerDependencies: typescript: '>=3.7.0' dependencies: - typescript: 4.9.5 - dev: true + typescript: 5.1.6 /ts-node@10.9.1(@types/node@18.16.8)(typescript@4.9.5): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} @@ -10757,7 +9163,7 @@ packages: yn: 3.1.1 dev: true - /ts-node@10.9.1(@types/node@18.16.8)(typescript@5.0.4): + /ts-node@10.9.1(@types/node@18.16.8)(typescript@5.1.6): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -10783,17 +9189,17 @@ packages: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.0.4 + typescript: 5.1.6 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: true - /tsconfig-paths@4.1.0: - resolution: {integrity: sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==} + /tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} dependencies: json5: 2.2.3 - minimist: 1.2.7 + minimist: 1.2.8 strip-bom: 3.0.0 dev: true @@ -10805,17 +9211,17 @@ packages: resolution: {integrity: sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==} dev: true - /tslib@2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + /tslib@2.6.1: + resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} - /tsutils@3.21.0(typescript@4.9.5): + /tsutils@3.21.0(typescript@5.1.6): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 4.9.5 + typescript: 5.1.6 dev: true /tunnel-agent@0.6.0: @@ -10885,13 +9291,6 @@ packages: turbo-windows-arm64: 1.9.4 dev: true - /type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - dev: true - /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -10914,8 +9313,8 @@ packages: engines: {node: '>=10'} dev: true - /typechain@8.1.1(typescript@4.9.5): - resolution: {integrity: sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ==} + /typechain@8.3.1(typescript@5.1.6): + resolution: {integrity: sha512-fA7clol2IP/56yq6vkMTR+4URF1nGjV82Wx6Rf09EsqD4tkzMAvEaqYxVFCavJm/1xaRga/oD55K+4FtuXwQOQ==} hasBin: true peerDependencies: typescript: '>=4.3.0' @@ -10929,11 +9328,10 @@ packages: mkdirp: 1.0.4 prettier: 2.7.1 ts-command-line-args: 2.3.1 - ts-essentials: 7.0.3(typescript@4.9.5) - typescript: 4.9.5 + ts-essentials: 7.0.3(typescript@5.1.6) + typescript: 5.1.6 transitivePeerDependencies: - supports-color - dev: true /typescript@4.9.5: resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} @@ -10941,29 +9339,18 @@ packages: hasBin: true dev: true - /typescript@5.0.4: - resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} - engines: {node: '>=12.20'} + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} hasBin: true - dev: true /typical@4.0.0: resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} engines: {node: '>=8'} - dev: true /typical@5.2.0: resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} engines: {node: '>=8'} - dev: true - - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true /uint8-varint@1.0.6: resolution: {integrity: sha512-Z0ujO4rxPwxTdLsSI5ke+bdl9hjJ1xiOakBPZeWUI/u6YBGCEGTW6b90SMlhxSGButKVPkL9fMFUDnqThQYTGg==} @@ -11027,7 +9414,6 @@ packages: /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} - dev: true /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} @@ -11052,17 +9438,6 @@ packages: engines: {node: '>=4'} dev: true - /update-browserslist-db@1.0.10(browserslist@4.21.4): - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.4 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: @@ -11093,24 +9468,16 @@ packages: engines: {node: '>=0.10.0'} dev: true - /user-home@2.0.0: - resolution: {integrity: sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==} - engines: {node: '>=0.10.0'} - dependencies: - os-homedir: 1.0.2 - dev: true - /utf8-byte-length@1.0.4: resolution: {integrity: sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==} dev: true /utf8@3.0.0: resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - dev: true + dev: false /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true /util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} @@ -11176,7 +9543,7 @@ packages: number-to-bn: 1.7.0 randombytes: 2.1.0 utf8: 3.0.0 - dev: true + dev: false /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -11238,13 +9605,6 @@ packages: is-typed-array: 1.1.10 dev: true - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -11256,7 +9616,7 @@ packages: /wide-align@1.1.3: resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==} dependencies: - string-width: 2.1.1 + string-width: 1.0.2 dev: true /wide-align@1.1.5: @@ -11265,13 +9625,6 @@ packages: string-width: 4.2.3 dev: true - /widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} - dependencies: - string-width: 4.2.3 - dev: true - /winston-daily-rotate-file@4.7.1(winston@3.8.2): resolution: {integrity: sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==} engines: {node: '>=8'} @@ -11316,17 +9669,12 @@ packages: engines: {node: '>=0.10.0'} dev: true - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - /wordwrapjs@4.0.1: resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} engines: {node: '>=8.0.0'} dependencies: reduce-flatten: 2.0.0 typical: 5.2.0 - dev: true /workerpool@6.1.0: resolution: {integrity: sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==} @@ -11356,14 +9704,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /write@1.0.3: - resolution: {integrity: sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==} - engines: {node: '>=4'} - dependencies: - mkdirp: 0.5.6 - dev: true /ws@7.4.6: resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} @@ -11450,8 +9790,8 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true - /yaml@2.2.2: - resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==} + /yaml@2.3.1: + resolution: {integrity: sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==} engines: {node: '>= 14'} dev: true diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml new file mode 100644 index 0000000000000..6318c267c2cc7 --- /dev/null +++ b/web/pnpm-workspace.yaml @@ -0,0 +1,5 @@ +packages: + - "packages/test" + - "packages/api" + - "packages/contract-types" + - "packages/test-helpers" diff --git a/core/tsconfig.json b/web/tsconfig.json similarity index 100% rename from core/tsconfig.json rename to web/tsconfig.json diff --git a/core/turbo.json b/web/turbo.json similarity index 100% rename from core/turbo.json rename to web/turbo.json