From 575ee7afe8d453373020469854f9cb109fa46877 Mon Sep 17 00:00:00 2001 From: NindoK Date: Fri, 19 Dec 2025 19:28:46 +0100 Subject: [PATCH] First working version. Missing minor implementations on V2 --- .github/workflows/check-contracts-clients.yml | 52 + .github/workflows/contracts.yml | 15 +- .github/workflows/control.yml | 7 +- .github/workflows/labels.yml | 3 +- .github/workflows/npm-publish.yml | 1 + .github/workflows/relayer.yml | 8 +- .github/workflows/release-relayer.yml | 3 +- .github/workflows/smoke-tests.yml | 12 +- contracts/scripts/DeployBeefyLocal.sol | 54 + contracts/scripts/DeployGatewayUpgrade.sol | 52 + contracts/scripts/DeployLocal.sol | 121 +- contracts/scripts/DeployLocalGateway.sol | 63 ++ contracts/scripts/DeployLocalGatewayLogic.sol | 35 + contracts/scripts/FundGateway.sol | 4 +- contracts/scripts/HelperConfig.sol | 191 ++++ contracts/scripts/chain_data.json | 84 ++ contracts/src/AgentExecutor.sol | 2 +- contracts/src/Gateway.sol | 189 +++- contracts/src/Operators.sol | 54 + contracts/src/interfaces/IMiddlewareBasic.sol | 53 + contracts/src/interfaces/IOGateway.sol | 94 ++ contracts/src/libraries/OSubstrateTypes.sol | 43 + contracts/src/storage/GatewayCoreStorage.sol | 71 ++ contracts/src/upgrades/Gateway202502.sol | 23 + .../src/upgrades/GatewayTanssi202506.sol | 18 + .../src/upgrades/GatewayTanssi202507.sol | 18 + .../src/upgrades/GatewayTanssi202509.sol | 23 + contracts/src/v1/Calls.sol | 27 + contracts/src/v1/Types.sol | 33 +- contracts/src/v2/Types.sol | 8 + contracts/test/GatewayV1.t.sol | 397 ++++--- .../test/data/beefy-final-bitfield-0.json | 2 +- .../test/data/beefy-final-bitfield-3.json | 2 +- contracts/test/override_test/Gateway.t.sol | 802 +++++++++++++ .../test_vector_message_validator_1000.json | 1006 +++++++++++++++++ .../test_vector_message_validator_400.json | 406 +++++++ .../test_vector_message_validator_50.json | 56 + 37 files changed, 3734 insertions(+), 298 deletions(-) create mode 100644 .github/workflows/check-contracts-clients.yml create mode 100644 contracts/scripts/DeployBeefyLocal.sol create mode 100644 contracts/scripts/DeployGatewayUpgrade.sol create mode 100644 contracts/scripts/DeployLocalGateway.sol create mode 100644 contracts/scripts/DeployLocalGatewayLogic.sol create mode 100644 contracts/scripts/HelperConfig.sol create mode 100644 contracts/scripts/chain_data.json create mode 100644 contracts/src/Operators.sol create mode 100644 contracts/src/interfaces/IMiddlewareBasic.sol create mode 100644 contracts/src/interfaces/IOGateway.sol create mode 100644 contracts/src/libraries/OSubstrateTypes.sol create mode 100644 contracts/src/storage/GatewayCoreStorage.sol create mode 100644 contracts/src/upgrades/Gateway202502.sol create mode 100644 contracts/src/upgrades/GatewayTanssi202506.sol create mode 100644 contracts/src/upgrades/GatewayTanssi202507.sol create mode 100644 contracts/src/upgrades/GatewayTanssi202509.sol create mode 100644 contracts/test/override_test/Gateway.t.sol create mode 100644 contracts/test/snowbridge-data/test_vector_message_validator_1000.json create mode 100644 contracts/test/snowbridge-data/test_vector_message_validator_400.json create mode 100644 contracts/test/snowbridge-data/test_vector_message_validator_50.json diff --git a/.github/workflows/check-contracts-clients.yml b/.github/workflows/check-contracts-clients.yml new file mode 100644 index 000000000..46a4c5a19 --- /dev/null +++ b/.github/workflows/check-contracts-clients.yml @@ -0,0 +1,52 @@ +# Check if Go clients consistent with contracts +name: Check Contracts Clients + +on: + pull_request: + # TODO: Remove test branch after testing + branches: ["tanssi-main"] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-contracts-clients: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check jq + run: jq --version + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.23" + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: "v1.1.0" + + - name: Show Forge version + run: forge --version + + - name: Install abigen + run: go install github.com/ethereum/go-ethereum/cmd/abigen@v1.14.11 + + - name: Check abigen + run: abigen --version + + - name: Build Contracts + working-directory: contracts + run: | + forge build + + - name: Generate clients + working-directory: relayer + run: | + go generate ./... + + - name: Check if go contract bindings are up-to-date + run: git diff --exit-code ./relayer/contracts || (echo "The contract bindings are not up-to-date against contracts." && exit 1) diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml index b2c83c08f..6a7a28045 100644 --- a/.github/workflows/contracts.yml +++ b/.github/workflows/contracts.yml @@ -12,9 +12,13 @@ on: - "contracts/**" - "!contracts/**/README.md" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: - runs-on: snowbridge-runner + runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v1 @@ -25,13 +29,16 @@ jobs: - name: Test working-directory: contracts run: forge test + env: + RPC_URL: ${{ secrets.RPC_URL }} - name: Coverage working-directory: contracts - run: forge coverage --report=lcov + run: forge coverage --report=lcov --via-ir + env: + RPC_URL: ${{ secrets.RPC_URL }} - name: Upload coverage reports to Codecov with GitHub Action - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v3 with: working-directory: contracts - token: ${{ secrets.CODECOV_TOKEN }} files: lcov.info flags: solidity diff --git a/.github/workflows/control.yml b/.github/workflows/control.yml index 636671d56..8903caa97 100644 --- a/.github/workflows/control.yml +++ b/.github/workflows/control.yml @@ -10,9 +10,13 @@ on: paths: - "control/**" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: control: - runs-on: snowbridge-runner + runs-on: ubuntu-latest env: CARGO_INCREMENTAL: 0 RUST_BACKTRACE: 1 @@ -59,4 +63,3 @@ jobs: - name: Build Westend run: | nix develop -c sh -c 'cd control && cargo build --features westend' - diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 66376f6e3..ce8af9705 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -5,6 +5,7 @@ on: jobs: labeler: + if: false permissions: contents: read pull-requests: write @@ -12,4 +13,4 @@ jobs: steps: - uses: actions/labeler@v5 with: - sync-labels: true + sync-labels: true diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index bb5ecdc8e..ddc1ecbb6 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -10,6 +10,7 @@ env: jobs: publish: + if: false runs-on: snowbridge-runner timeout-minutes: 15 steps: diff --git a/.github/workflows/relayer.yml b/.github/workflows/relayer.yml index af5adc5a0..2c6e06fa4 100644 --- a/.github/workflows/relayer.yml +++ b/.github/workflows/relayer.yml @@ -10,9 +10,13 @@ on: paths: - "relayer/**" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: - runs-on: snowbridge-runner + runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v1 @@ -22,7 +26,7 @@ jobs: - name: setup go uses: actions/checkout@v4 with: - go-version: '^1.23.0' + go-version: "^1.22.5" - name: check go version run: go version diff --git a/.github/workflows/release-relayer.yml b/.github/workflows/release-relayer.yml index 89af18fe9..fe3bf9e45 100644 --- a/.github/workflows/release-relayer.yml +++ b/.github/workflows/release-relayer.yml @@ -13,6 +13,7 @@ env: IMAGE_NAME: snowfork/snowbridge-relay jobs: + if: false release-relayer: runs-on: snowbridge-runner timeout-minutes: 15 @@ -29,7 +30,7 @@ jobs: - name: Setup go uses: actions/checkout@v4 with: - go-version: "^1.23.0" + go-version: "^1.21.0" - name: Install Go tools run: > diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 2fab34eea..1b4694380 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -9,9 +9,13 @@ on: # Runs at 8:00 AM every day - cron: "0 8 * * *" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: smoketests: - runs-on: snowbridge-runner + runs-on: ubuntu-latest env: CARGO_INCREMENTAL: 0 RUST_BACKTRACE: 1 @@ -40,7 +44,7 @@ jobs: run: echo "POLKADOT_SDK_DIR=./polkadot-sdk" >> $GITHUB_ENV - name: Create directories run: mkdir -p $OUTPUT_DIR && mkdir -p $LOG_DIR - - uses: actions/cache@v1 + - uses: actions/cache@v3 with: path: | ~/.cargo/registry @@ -63,12 +67,12 @@ jobs: ./scripts/run-smoketests.sh' continue-on-error: true - name: Save start-services log file - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: start-services.log path: "${{ env.LOG_DIR }}/start-services.log" - name: Save beacon-relay log file - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: beacon-relay.log path: "${{ env.OUTPUT_DIR }}/beacon-relay.log" diff --git a/contracts/scripts/DeployBeefyLocal.sol b/contracts/scripts/DeployBeefyLocal.sol new file mode 100644 index 000000000..e097bc0af --- /dev/null +++ b/contracts/scripts/DeployBeefyLocal.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {Script, console2} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +import {BeefyClient} from "../src/BeefyClient.sol"; +import {HelperConfig} from "./HelperConfig.sol"; + +contract DeployBeefyClient is Script { + using stdJson for string; + + function setUp() public {} + + function run() public { + HelperConfig helperConfig = new HelperConfig(""); + HelperConfig.BeefyClientConfig memory beefyClientConfig = + helperConfig.getBeefyClientConfig(); + + vm.startBroadcast(); + + // 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")); + + BeefyClient.ValidatorSet memory current = BeefyClient.ValidatorSet( + uint128(beefyCheckpointRaw.readUint(".current.id")), + uint128(beefyCheckpointRaw.readUint(".current.length")), + beefyCheckpointRaw.readBytes32(".current.root") + ); + BeefyClient.ValidatorSet memory next = BeefyClient.ValidatorSet( + uint128(beefyCheckpointRaw.readUint(".next.id")), + uint128(beefyCheckpointRaw.readUint(".next.length")), + beefyCheckpointRaw.readBytes32(".next.root") + ); + + BeefyClient beefyClient = new BeefyClient( + beefyClientConfig.randaoCommitDelay, + beefyClientConfig.randaoCommitExpiration, + beefyClientConfig.minimumSignatures, + startBlock, + current, + next + ); + + console2.log("BeefyClient: ", address(beefyClient)); + + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/DeployGatewayUpgrade.sol b/contracts/scripts/DeployGatewayUpgrade.sol new file mode 100644 index 000000000..4c7a1cf40 --- /dev/null +++ b/contracts/scripts/DeployGatewayUpgrade.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {console2} from "forge-std/console2.sol"; +import {Script} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +import {GatewayTanssi202509} from "../src/upgrades/GatewayTanssi202509.sol"; +import {HelperConfig} from "./HelperConfig.sol"; +import {UpgradeParams} from "../src/v1/Types.sol"; +import {AgentExecutor} from "../src/AgentExecutor.sol"; + +contract DeployLocal is Script { + using stdJson for string; + + function setUp() public {} + + function run() public { + HelperConfig helperConfig = new HelperConfig(""); + _deploy(helperConfig); + } + + function run(string calldata testnet) public { + HelperConfig helperConfig = new HelperConfig(testnet); + _deploy(helperConfig); + } + + function _deploy(HelperConfig helperConfig) private { + vm.startBroadcast(); + HelperConfig.GatewayConfig memory gatewayConfig = helperConfig.getGatewayConfig(); + + // Needed for the native transfer feature + AgentExecutor agentExecutor = new AgentExecutor(); + + GatewayTanssi202509 gatewayLogic = + new GatewayTanssi202509(address(gatewayConfig.beefyClient), address(agentExecutor)); + + console2.log("AgentExecutor: ", address(agentExecutor)); + console2.log("Gateway logic impl: ", address(gatewayLogic)); + console2.log("Gateway logic codehash: "); + console2.logBytes32(address(gatewayLogic).codehash); + UpgradeParams memory params = UpgradeParams({ + impl: address(gatewayLogic), + implCodeHash: address(gatewayLogic).codehash, + initParams: bytes("") + }); + + console2.logBytes(abi.encode(params)); + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/DeployLocal.sol b/contracts/scripts/DeployLocal.sol index fea2f9469..720c2d228 100644 --- a/contracts/scripts/DeployLocal.sol +++ b/contracts/scripts/DeployLocal.sol @@ -2,70 +2,77 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.28; -import {WETH9} from "canonical-weth/WETH9.sol"; import {Script} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; import {BeefyClient} from "../src/BeefyClient.sol"; - -import {IGatewayV1} from "../src/v1/IGateway.sol"; -import {IGatewayV2} from "../src/v2/IGateway.sol"; +import {console2} from "forge-std/console2.sol"; import {GatewayProxy} from "../src/GatewayProxy.sol"; import {Gateway} from "../src/Gateway.sol"; -import {MockGatewayV2} from "../test/mocks/MockGatewayV2.sol"; -import {Agent} from "../src/Agent.sol"; import {AgentExecutor} from "../src/AgentExecutor.sol"; -import {Constants} from "../src/Constants.sol"; -import {ChannelID, ParaID, OperatingMode} from "../src/Types.sol"; +import {OperatingMode} from "../src/Types.sol"; +import {HelperConfig} from "./HelperConfig.sol"; +import {WETH9} from "canonical-weth/WETH9.sol"; +import {IGatewayV1} from "../src/Types.sol"; import {Initializer} from "../src/Initializer.sol"; -import {SafeNativeTransfer} from "../src/utils/SafeTransfer.sol"; -import {stdJson} from "forge-std/StdJson.sol"; -import {UD60x18, ud60x18} from "prb/math/src/UD60x18.sol"; -import {HelloWorld} from "../test/mocks/HelloWorld.sol"; contract DeployLocal 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); + HelperConfig helperConfig = new HelperConfig(""); + _deploy(helperConfig); + } + function run(string calldata testnet) public { + HelperConfig helperConfig = new HelperConfig(testnet); + _deploy(helperConfig); + } + + function _deploy(HelperConfig helperConfig) public { + HelperConfig.GatewayConfig memory gatewayConfig = helperConfig.getGatewayConfig(); + HelperConfig.GatewayInitConfig memory gatewayInitConfig = + helperConfig.getGatewayInitConfig(); + HelperConfig.BeefyClientConfig memory beefyClientConfig = + helperConfig.getBeefyClientConfig(); + vm.startBroadcast(); + + BeefyClient beefyClient; // 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")); - - BeefyClient.ValidatorSet memory current = BeefyClient.ValidatorSet( - uint128(beefyCheckpointRaw.readUint(".current.id")), - uint128(beefyCheckpointRaw.readUint(".current.length")), - beefyCheckpointRaw.readBytes32(".current.root") - ); - BeefyClient.ValidatorSet memory next = BeefyClient.ValidatorSet( - uint128(beefyCheckpointRaw.readUint(".next.id")), - uint128(beefyCheckpointRaw.readUint(".next.length")), - beefyCheckpointRaw.readBytes32(".next.root") - ); - - uint256 randaoCommitDelay = vm.envUint("RANDAO_COMMIT_DELAY"); - uint256 randaoCommitExpiration = vm.envUint("RANDAO_COMMIT_EXP"); - uint256 minimumSignatures = vm.envUint("MINIMUM_REQUIRED_SIGNATURES"); - BeefyClient beefyClient = new BeefyClient( - randaoCommitDelay, randaoCommitExpiration, minimumSignatures, startBlock, current, next - ); - - uint8 foreignTokenDecimals = uint8(vm.envUint("FOREIGN_TOKEN_DECIMALS")); - uint128 maxDestinationFee = uint128(vm.envUint("RESERVE_TRANSFER_MAX_DESTINATION_FEE")); + { + 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")); + + BeefyClient.ValidatorSet memory current = BeefyClient.ValidatorSet( + uint128(beefyCheckpointRaw.readUint(".current.id")), + uint128(beefyCheckpointRaw.readUint(".current.length")), + beefyCheckpointRaw.readBytes32(".current.root") + ); + BeefyClient.ValidatorSet memory next = BeefyClient.ValidatorSet( + uint128(beefyCheckpointRaw.readUint(".next.id")), + uint128(beefyCheckpointRaw.readUint(".next.length")), + beefyCheckpointRaw.readBytes32(".next.root") + ); + + beefyClient = new BeefyClient( + beefyClientConfig.randaoCommitDelay, + beefyClientConfig.randaoCommitExpiration, + beefyClientConfig.minimumSignatures, + startBlock, + current, + next + ); + } AgentExecutor executor = new AgentExecutor(); Gateway gatewayLogic = new Gateway(address(beefyClient), address(executor)); - bool rejectOutboundMessages = vm.envBool("REJECT_OUTBOUND_MESSAGES"); OperatingMode defaultOperatingMode; - if (rejectOutboundMessages) { + if (gatewayInitConfig.rejectOutboundMessages) { defaultOperatingMode = OperatingMode.RejectingOutboundMessages; } else { defaultOperatingMode = OperatingMode.Normal; @@ -73,30 +80,28 @@ contract DeployLocal is Script { Initializer.Config memory config = Initializer.Config({ mode: defaultOperatingMode, - deliveryCost: uint128(vm.envUint("DELIVERY_COST")), - registerTokenFee: uint128(vm.envUint("REGISTER_TOKEN_FEE")), - assetHubCreateAssetFee: uint128(vm.envUint("CREATE_ASSET_FEE")), - assetHubReserveTransferFee: uint128(vm.envUint("RESERVE_TRANSFER_FEE")), - exchangeRate: ud60x18(vm.envUint("EXCHANGE_RATE")), - multiplier: ud60x18(vm.envUint("FEE_MULTIPLIER")), - foreignTokenDecimals: foreignTokenDecimals, - maxDestinationFee: maxDestinationFee + deliveryCost: gatewayInitConfig.deliveryCost, + registerTokenFee: gatewayInitConfig.registerTokenFee, + assetHubCreateAssetFee: gatewayInitConfig.assetHubCreateAssetFee, + assetHubReserveTransferFee: gatewayInitConfig.assetHubReserveTransferFee, + exchangeRate: gatewayInitConfig.exchangeRate, + multiplier: gatewayInitConfig.multiplier, + foreignTokenDecimals: gatewayConfig.foreignTokenDecimals, + maxDestinationFee: gatewayConfig.maxDestinationFee }); GatewayProxy gateway = new GatewayProxy(address(gatewayLogic), abi.encode(config)); + console2.log("BeefyClient: ", address(beefyClient)); + console2.log("Gateway impl: ", address(gatewayLogic)); + console2.log("gateway address: ", address(gateway)); // Deploy WETH for testing new WETH9(); - // For testing call contract - new HelloWorld(); - - // Fund the gateway proxy contract. Used to reward relayers + // Fund the gateway proxy contract. Used to reward relayers. uint256 initialDeposit = vm.envUint("GATEWAY_PROXY_INITIAL_DEPOSIT"); - IGatewayV1(address(gateway)).depositEther{value: initialDeposit}(); - // Deploy MockGatewayV2 for testing - new MockGatewayV2(); + IGatewayV1(address(gateway)).depositEther{value: initialDeposit}(); vm.stopBroadcast(); } diff --git a/contracts/scripts/DeployLocalGateway.sol b/contracts/scripts/DeployLocalGateway.sol new file mode 100644 index 000000000..1a99d1ddc --- /dev/null +++ b/contracts/scripts/DeployLocalGateway.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {console2} from "forge-std/console2.sol"; +import {Script} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +import {GatewayProxy} from "../src/GatewayProxy.sol"; +import {Gateway} from "../src/Gateway.sol"; +import {OperatingMode} from "../src/Types.sol"; +import {HelperConfig} from "./HelperConfig.sol"; +import {Initializer} from "../src/Initializer.sol"; + +contract DeployLocal is Script { + using stdJson for string; + + function setUp() public {} + + function run() public { + HelperConfig helperConfig = new HelperConfig(""); + _deploy(helperConfig); + } + + function run(string calldata testnet) public { + HelperConfig helperConfig = new HelperConfig(testnet); + _deploy(helperConfig); + } + + function _deploy(HelperConfig helperConfig) private { + vm.startBroadcast(); + HelperConfig.GatewayConfig memory gatewayConfig = helperConfig.getGatewayConfig(); + HelperConfig.GatewayInitConfig memory gatewayInitConfig = + helperConfig.getGatewayInitConfig(); + + Gateway gatewayLogic = + new Gateway(address(gatewayConfig.beefyClient), address(gatewayConfig.agentExecutor)); + + OperatingMode defaultOperatingMode; + if (gatewayInitConfig.rejectOutboundMessages) { + defaultOperatingMode = OperatingMode.RejectingOutboundMessages; + } else { + defaultOperatingMode = OperatingMode.Normal; + } + + Initializer.Config memory config = Initializer.Config({ + mode: defaultOperatingMode, + deliveryCost: gatewayInitConfig.deliveryCost, + registerTokenFee: gatewayInitConfig.registerTokenFee, + assetHubCreateAssetFee: gatewayInitConfig.assetHubCreateAssetFee, + assetHubReserveTransferFee: gatewayInitConfig.assetHubReserveTransferFee, + exchangeRate: gatewayInitConfig.exchangeRate, + multiplier: gatewayInitConfig.multiplier, + foreignTokenDecimals: gatewayConfig.foreignTokenDecimals, + maxDestinationFee: gatewayConfig.maxDestinationFee + }); + + GatewayProxy gateway = new GatewayProxy(address(gatewayLogic), abi.encode(config)); + console2.log("Gateway impl: ", address(gatewayLogic)); + console2.log("gateway address: ", address(gateway)); + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/DeployLocalGatewayLogic.sol b/contracts/scripts/DeployLocalGatewayLogic.sol new file mode 100644 index 000000000..32b54b464 --- /dev/null +++ b/contracts/scripts/DeployLocalGatewayLogic.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {AgentExecutor} from "../src/AgentExecutor.sol"; +import {Gateway} from "../src//Gateway.sol"; +import {ParaID} from "../src//Types.sol"; +import {Script} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +contract DeployLocalGatewayLogic is Script { + using stdJson for string; + + function setUp() public {} + + function run() public { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.rememberKey(privateKey); + vm.startBroadcast(deployer); + + address beefyClient = vm.envAddress("BEEFY_CLIENT_CONTRACT_ADDRESS"); + + ParaID bridgeHubParaID = ParaID.wrap(uint32(vm.envUint("BRIDGE_HUB_PARAID"))); + bytes32 bridgeHubAgentID = vm.envBytes32("BRIDGE_HUB_AGENT_ID"); + + uint8 foreignTokenDecimals = uint8(vm.envUint("FOREIGN_TOKEN_DECIMALS")); + uint128 maxDestinationFee = uint128(vm.envUint("RESERVE_TRANSFER_MAX_DESTINATION_FEE")); + + AgentExecutor executor = new AgentExecutor(); + + new Gateway(address(beefyClient), address(executor)); + + vm.stopBroadcast(); + } +} diff --git a/contracts/scripts/FundGateway.sol b/contracts/scripts/FundGateway.sol index de8d4033e..1eadd6346 100644 --- a/contracts/scripts/FundGateway.sol +++ b/contracts/scripts/FundGateway.sol @@ -5,8 +5,8 @@ pragma solidity 0.8.28; import {WETH9} from "canonical-weth/WETH9.sol"; import {Script} from "forge-std/Script.sol"; import {BeefyClient} from "../src/BeefyClient.sol"; -import {IGatewayV1} from "../src/v1/IGateway.sol"; -import {IGatewayV2} from "../src/v2/IGateway.sol"; + +import {IGatewayV1} from "../src/Types.sol"; import {GatewayProxy} from "../src/GatewayProxy.sol"; import {Gateway} from "../src/Gateway.sol"; import {Agent} from "../src/Agent.sol"; diff --git a/contracts/scripts/HelperConfig.sol b/contracts/scripts/HelperConfig.sol new file mode 100644 index 000000000..83d1e51be --- /dev/null +++ b/contracts/scripts/HelperConfig.sol @@ -0,0 +1,191 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity 0.8.28; + +import {console2, Script} from "forge-std/Script.sol"; +import {UD60x18, ud60x18} from "prb/math/src/UD60x18.sol"; +import {ParaID} from "../src/Types.sol"; + +contract HelperConfig is Script { + BeefyClientConfig public activeBeefyClientConfig; + GatewayConfig public activeGatewayConfig; + GatewayInitConfig public activeGatewayInitConfig; + + struct BeefyClientConfig { + uint256 randaoCommitDelay; + uint256 randaoCommitExpiration; + uint256 minimumSignatures; + } + + struct GatewayConfig { + address beefyClient; + address agentExecutor; + ParaID bridgeHubParaID; + bytes32 bridgeHubAgentID; + uint8 foreignTokenDecimals; + uint128 maxDestinationFee; + } + + struct GatewayInitConfig { + ParaID assetHubParaID; + bytes32 assetHubAgentID; + bool rejectOutboundMessages; + uint128 deliveryCost; + uint128 registerTokenFee; + uint128 assetHubCreateAssetFee; + uint128 assetHubReserveTransferFee; + UD60x18 exchangeRate; + UD60x18 multiplier; + } + + uint256 public DEFAULT_ANVIL_PRIVATE_KEY = + 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6; + + constructor(string memory testnet) { + (activeBeefyClientConfig, activeGatewayConfig, activeGatewayInitConfig) = + getChainConfig(testnet); + } + + function getBeefyClientConfig() + public + view + returns (BeefyClientConfig memory beefyClientConfig) + { + return activeBeefyClientConfig; + } + + function getGatewayConfig() public view returns (GatewayConfig memory gatewayConfig) { + return activeGatewayConfig; + } + + function getGatewayInitConfig() + public + view + returns (GatewayInitConfig memory gatewayInitConfig) + { + return activeGatewayInitConfig; + } + + function getChainConfig(string memory testnet) + public + view + returns ( + BeefyClientConfig memory beefyClientConfig, + GatewayConfig memory gatewayConfig, + GatewayInitConfig memory gatewayInitConfig + ) + { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/scripts/chain_data.json"); + string memory json = vm.readFile(path); + + //! Make sure chainid is present in the json or this will just revert without giving any information + uint256 chainId = block.chainid; + string memory jsonPath = string.concat("$.", vm.toString(chainId)); + if ( + (keccak256(abi.encodePacked(testnet)) == keccak256("stagelight") + || keccak256(abi.encodePacked(testnet)) == keccak256("dancelight")) + && block.chainid == 11_155_111 + ) { + jsonPath = string.concat(jsonPath, string.concat(".", testnet)); + } + + beefyClientConfig = _loadBeefyClientConfig(json, jsonPath); + gatewayConfig = _loadGatewayConfig(json, jsonPath); + gatewayInitConfig = _loadGatewayInitConfig(json, jsonPath); + } + + function _loadBeefyClientConfig(string memory json, string memory jsonPath) + private + pure + returns (BeefyClientConfig memory beefyClientConfig) + { + beefyClientConfig = BeefyClientConfig({ + randaoCommitDelay: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".randomCommitDelay")), (uint256) + ), + randaoCommitExpiration: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".randaoCommitExpiration")), (uint256) + ), + minimumSignatures: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".minimumSignatures")), (uint256) + ) + }); + } + + function _loadGatewayConfig(string memory json, string memory jsonPath) + private + pure + returns (GatewayConfig memory gatewayConfig) + { + gatewayConfig = GatewayConfig({ + beefyClient: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".beefyClient")), (address) + ), + agentExecutor: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".agentExecutor")), (address) + ), + bridgeHubParaID: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".bridgeHubParaID")), (ParaID) + ), + bridgeHubAgentID: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".bridgeHubAgentID")), (bytes32) + ), + foreignTokenDecimals: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".foreignTokenDecimals")), (uint8) + ), + maxDestinationFee: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".maxDestinationFee")), (uint128) + ) + }); + } + + function _loadGatewayInitConfig(string memory json, string memory jsonPath) + private + pure + returns (GatewayInitConfig memory gatewayInitConfig) + { + gatewayInitConfig = GatewayInitConfig({ + assetHubParaID: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".assetHubParaID")), (ParaID) + ), + assetHubAgentID: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".assetHubAgentID")), (bytes32) + ), + rejectOutboundMessages: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".rejectOutboundMessages")), (bool) + ), + deliveryCost: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".deliveryCost")), (uint128) + ), + registerTokenFee: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".registerTokenFee")), (uint128) + ), + assetHubCreateAssetFee: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".assetHubCreateAssetFee")), (uint128) + ), + assetHubReserveTransferFee: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".assetHubReserveTransferFee")), + (uint128) + ), + exchangeRate: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".exchangeRate")), (UD60x18) + ), + multiplier: abi.decode( + vm.parseJson(json, string.concat(jsonPath, ".multiplier")), (UD60x18) + ) + }); + } +} diff --git a/contracts/scripts/chain_data.json b/contracts/scripts/chain_data.json new file mode 100644 index 000000000..b3606e6cc --- /dev/null +++ b/contracts/scripts/chain_data.json @@ -0,0 +1,84 @@ +{ + "1": { + "beefyClient": "0x68cfb0df884e488e362690408231c316ed7348af", + "agentExecutor": "0x5e06dde7533d94aE25f3ee12c8ACe848b618E5e5", + "bridgeHubParaID": 1, + "bridgeHubAgentID": "0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + "foreignTokenDecimals": 12, + "maxDestinationFee": 1000000000000000, + "assetHubParaID": 1, + "assetHubAgentID": "0x9ba4d8cfc1cdf812338aa6457aa5510348526d933108b4106162474231b4cbe5", + "rejectOutboundMessages": false, + "deliveryCost": 695335506, + "registerTokenFee": 1000000000000000000, + "assetHubCreateAssetFee": 911996796338, + "assetHubReserveTransferFee": 540504664494, + "exchangeRate": 2500000000000000, + "multiplier": 1000000000000000000, + "randomCommitDelay": 3, + "randaoCommitExpiration": 8, + "minimumSignatures": 16 + }, + "31337": { + "beefyClient": "0x68cfb0df884e488e362690408231c316ed7348af", + "agentExecutor": "0xAD4a6D5DAe036fe490b34C08c7085C6B2Ae69969", + "bridgeHubParaID": 1, + "bridgeHubAgentID": "0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + "foreignTokenDecimals": 12, + "maxDestinationFee": 1000000000000000, + "assetHubParaID": 1, + "assetHubAgentID": "0x9ba4d8cfc1cdf812338aa6457aa5510348526d933108b4106162474231b4cbe5", + "rejectOutboundMessages": false, + "deliveryCost": 695335506, + "registerTokenFee": 1000000000000000000, + "assetHubCreateAssetFee": 911996796338, + "assetHubReserveTransferFee": 540504664494, + "exchangeRate": 2500000000000000, + "multiplier": 1000000000000000000, + "randomCommitDelay": 3, + "randaoCommitExpiration": 8, + "minimumSignatures": 16 + }, + "11155111": { + "stagelight": { + "beefyClient": "0xD4C3B70Ac1547D66Bc89F8607C58Dd544412e8B7", + "agentExecutor": "0xd1668df5B8ff617De25544085aA126FCC9871559", + "bridgeHubParaID": 1, + "bridgeHubAgentID": "0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + "foreignTokenDecimals": 12, + "maxDestinationFee": 1000000000000000, + "assetHubParaID": 1, + "assetHubAgentID": "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "rejectOutboundMessages": false, + "deliveryCost": 695335506, + "registerTokenFee": 1000000000000000000, + "assetHubCreateAssetFee": 911996796338, + "assetHubReserveTransferFee": 540504664494, + "exchangeRate": 2500000000000000, + "multiplier": 1000000000000000000, + "randomCommitDelay": 3, + "randaoCommitExpiration": 8, + "minimumSignatures": 16 + }, + "dancelight": { + "beefyClient": "0xe8dd26d2ec505ac7e51740da84ba2ce9f01a2431", + "agentExecutor": "0xaA8fB051b48518391C655FAa146FF1da76C81755", + "bridgeHubParaID": 1, + "bridgeHubAgentID": "0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + "foreignTokenDecimals": 12, + "maxDestinationFee": 1000000000000000, + "assetHubParaID": 1, + "assetHubAgentID": "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", + "rejectOutboundMessages": false, + "deliveryCost": 695335506, + "registerTokenFee": 1000000000000000000, + "assetHubCreateAssetFee": 911996796338, + "assetHubReserveTransferFee": 540504664494, + "exchangeRate": 2500000000000000, + "multiplier": 1000000000000000000, + "randomCommitDelay": 3, + "randaoCommitExpiration": 8, + "minimumSignatures": 16 + } + } +} diff --git a/contracts/src/AgentExecutor.sol b/contracts/src/AgentExecutor.sol index 367838b8a..2cf0596f4 100644 --- a/contracts/src/AgentExecutor.sol +++ b/contracts/src/AgentExecutor.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.28; -import {ParaID} from "./Types.sol"; +import {ParaID} from "./v1/Types.sol"; import {SubstrateTypes} from "./SubstrateTypes.sol"; import {IERC20} from "./interfaces/IERC20.sol"; diff --git a/contracts/src/Gateway.sol b/contracts/src/Gateway.sol index 79fb7d2c9..3c14939d9 100644 --- a/contracts/src/Gateway.sol +++ b/contracts/src/Gateway.sol @@ -7,7 +7,6 @@ import {Verification} from "./Verification.sol"; import {Initializer} from "./Initializer.sol"; import {AgentExecutor} from "./AgentExecutor.sol"; import {Agent} from "./Agent.sol"; -import {IGatewayBase} from "./interfaces/IGatewayBase.sol"; import { OperatingMode, ParaID, @@ -43,10 +42,15 @@ import {Constants} from "./Constants.sol"; import {CoreStorage} from "./storage/CoreStorage.sol"; import {PricingStorage} from "./storage/PricingStorage.sol"; import {AssetsStorage} from "./storage/AssetsStorage.sol"; +import {GatewayCoreStorage} from "./storage/GatewayCoreStorage.sol"; import {UD60x18, ud60x18, convert} from "prb/math/src/UD60x18.sol"; -contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgradable { +import {IOGateway} from "./interfaces/IOGateway.sol"; +import {IMiddlewareBasic} from "./interfaces/IMiddlewareBasic.sol"; + +// TODO Fix interface imports +contract Gateway is IOGateway, IGatewayV1, IGatewayV2, IInitializable, IUpgradable { using Address for address; using SafeNativeTransfer for address payable; @@ -59,7 +63,25 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra // Message handlers can only be dispatched by the gateway itself modifier onlySelf() { if (msg.sender != address(this)) { - revert IGatewayBase.Unauthorized(); + revert Unauthorized(); + } + _; + } + + // Can only be called by the owner of the contract. + modifier onlyOwner() { + GatewayCoreStorage.Layout storage layout = GatewayCoreStorage.layout(); + if (msg.sender != layout.owner) { + revert Unauthorized(); + } + _; + } + + // Can only be called by the middleware + modifier onlyMiddleware() { + GatewayCoreStorage.Layout storage layout = GatewayCoreStorage.layout(); + if (msg.sender != layout.middleware) { + revert Unauthorized(); } _; } @@ -149,7 +171,7 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra // Ensure this message is not being replayed if (message.nonce != channel.inboundNonce + 1) { - revert IGatewayBase.InvalidNonce(); + revert InvalidNonce(); } // Increment nonce for origin. @@ -163,14 +185,14 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra // Verify that the commitment is included in a parachain header finalized by BEEFY. if (!_verifyCommitment(commitment, headerProof, false)) { - revert IGatewayBase.InvalidProof(); + revert InvalidProof(); } // Make sure relayers provide enough gas so that inner message dispatch // does not run out of gas. uint256 maxDispatchGas = message.maxDispatchGas; if (gasleft() < maxDispatchGas + DISPATCH_OVERHEAD_GAS_V1) { - revert IGatewayBase.NotEnoughGas(); + revert NotEnoughGas(); } bool success = true; @@ -214,11 +236,34 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra } else if (message.command == CommandV1.MintForeignToken) { try Gateway(this).v1_handleMintForeignToken{gas: maxDispatchGas}( message.channelID, message.params - ) {} catch { + ) {} + catch { + success = false; + } + } else if (message.command == CommandV1.ReportSlashes) { + // We need to put all this inside a generic try-catch, since we dont want to revert decoding nor anything + try Gateway(this).reportSlashes{gas: maxDispatchGas}(message.params) {} + catch Error(string memory err) { + emit UnableToProcessSlashMessageS(err); + success = false; + } catch (bytes memory err) { + emit UnableToProcessSlashMessageB(err); + success = false; + } + } else if (message.command == CommandV1.ReportRewards) { + try Gateway(this).sendRewards{gas: maxDispatchGas}( + message.channelID, message.params + ) {} + catch Error(string memory err) { + emit UnableToProcessRewardsMessageS(err); + success = false; + } catch (bytes memory err) { + emit UnableToProcessRewardsMessageB(err); success = false; } } else { success = false; + emit NotImplementedCommand(message.command); } // Calculate a gas refund, capped to protect against huge spikes in `tx.gasprice` @@ -240,6 +285,18 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra ); } + function transferOwnership(address newOwner) external onlyOwner { + GatewayCoreStorage.transferOwnership(newOwner); + } + + function setMiddleware(address middleware) external onlyOwner { + GatewayCoreStorage.setMiddleware(middleware); + } + + function s_middleware() external view returns (address) { + return GatewayCoreStorage.s_middleware(); + } + function operatingMode() external view @@ -328,6 +385,11 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra return CallsV1.tokenAddressOf(tokenID); } + // Send operators data to substrate + function sendOperatorsData(bytes32[] calldata data, uint48 epoch) external onlyMiddleware { + CallsV1.sendOperatorsData(data, epoch); + } + /** * APIv1 Inbound Message Handlers */ @@ -342,6 +404,11 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra HandlersV1.upgrade(data); } + /// Performs upgrade through the owner + function upgradeOnlyOwner(bytes calldata data) external onlyOwner { + Gateway(this).v1_handleUpgrade(data); + } + // @dev Set the operating mode of the gateway function v1_handleSetOperatingMode(bytes calldata data) external onlySelf { HandlersV1.setOperatingMode(data); @@ -375,6 +442,90 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra HandlersV1.mintForeignToken(channelID, data); } + // TODO TO move this to v1 and v2. + // @dev Mint foreign token from polkadot + function reportSlashes(bytes calldata data) external onlySelf { + GatewayCoreStorage.Layout storage layout = GatewayCoreStorage.layout(); + address middlewareAddress = layout.middleware; + // Dont process message if we dont have a middleware set + if (middlewareAddress == address(0)) { + revert MiddlewareNotSet(); + } + + // Decode + (IOGateway.SlashParams memory slashes) = abi.decode(data, (IOGateway.SlashParams)); + IMiddlewareBasic middleware = IMiddlewareBasic(middlewareAddress); + + // At most it will be 10, defined by + // https://github.com/moondance-labs/tanssi/blob/88e59e6e5afb198947690487f286b9ad7cd4cde6/chains/orchestrator-relays/runtime/dancelight/src/lib.rs#L1446 + for (uint256 i = 0; i < slashes.slashes.length; ++i) { + Slash memory slash = slashes.slashes[i]; + //TODO maxDispatchGas should be probably be defined for all slashes, not only for one + try middleware.slash(uint48(slash.epoch), slash.operatorKey, slash.slashFraction) {} + catch Error(string memory err) { + emit UnableToProcessIndividualSlashS( + slash.operatorKey, slash.slashFraction, slash.epoch, err + ); + continue; + } catch (bytes memory err) { + emit UnableToProcessIndividualSlashB( + slash.operatorKey, slash.slashFraction, slash.epoch, err + ); + continue; + } + } + } + + function sendRewards(ChannelID channelID, bytes calldata data) external onlySelf { + GatewayCoreStorage.Layout storage layout = GatewayCoreStorage.layout(); + address middlewareAddress = layout.middleware; + // Dont process message if we dont have a middleware set + if (middlewareAddress == address(0)) { + revert MiddlewareNotSet(); + } + + ( + uint256 epoch, + uint256 eraIndex, + uint256 totalPointsToken, + uint256 totalTokensInflated, + bytes32 rewardsRoot, + bytes32 foreignTokenId + ) = abi.decode(data, (uint256, uint256, uint256, uint256, bytes32, bytes32)); + + bytes memory foreignTokenData = + abi.encode(foreignTokenId, middlewareAddress, totalTokensInflated); + HandlersV1.mintForeignToken(channelID, foreignTokenData); + + address tokenAddress = CallsV1.tokenAddressOf(foreignTokenId); + + try IMiddlewareBasic(middlewareAddress) + .distributeRewards( + epoch, eraIndex, totalPointsToken, totalTokensInflated, rewardsRoot, tokenAddress + ) {} + catch Error(string memory err) { + revert EUnableToProcessRewardsS( + epoch, + eraIndex, + tokenAddress, + totalPointsToken, + totalTokensInflated, + rewardsRoot, + err + ); + } catch (bytes memory err) { + revert EUnableToProcessRewardsB( + epoch, + eraIndex, + tokenAddress, + totalPointsToken, + totalTokensInflated, + rewardsRoot, + err + ); + } + } + /** * APIv1 Internal functions */ @@ -418,7 +569,7 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra bytes32 leafHash = keccak256(abi.encode(message)); if ($.inboundNonce.get(message.nonce)) { - revert IGatewayBase.InvalidNonce(); + revert InvalidNonce(); } $.inboundNonce.set(message.nonce); @@ -428,7 +579,7 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra // Verify that the commitment is included in a parachain header finalized by BEEFY. if (!_verifyCommitment(commitment, headerProof, true)) { - revert IGatewayBase.InvalidProof(); + revert InvalidProof(); } // Dispatch the message payload @@ -525,39 +676,46 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra if (message.commands[i].kind == CommandKind.Upgrade) { try Gateway(this).v2_handleUpgrade{gas: message.commands[i].gas}( message.commands[i].payload - ) {} catch { + ) {} + catch { return false; } } else if (message.commands[i].kind == CommandKind.SetOperatingMode) { try Gateway(this).v2_handleSetOperatingMode{gas: message.commands[i].gas}( message.commands[i].payload - ) {} catch { + ) {} + catch { return false; } } else if (message.commands[i].kind == CommandKind.UnlockNativeToken) { try Gateway(this).v2_handleUnlockNativeToken{gas: message.commands[i].gas}( message.commands[i].payload - ) {} catch { + ) {} + catch { return false; } } else if (message.commands[i].kind == CommandKind.RegisterForeignToken) { try Gateway(this).v2_handleRegisterForeignToken{gas: message.commands[i].gas}( message.commands[i].payload - ) {} catch { + ) {} + catch { return false; } } else if (message.commands[i].kind == CommandKind.MintForeignToken) { try Gateway(this).v2_handleMintForeignToken{gas: message.commands[i].gas}( message.commands[i].payload - ) {} catch { + ) {} + catch { return false; } } else if (message.commands[i].kind == CommandKind.CallContract) { try Gateway(this).v2_handleCallContract{gas: message.commands[i].gas}( message.origin, message.commands[i].payload - ) {} catch { + ) {} + catch { return false; } + // TODO to add here new tanssi commands } else { // Unknown command return false; @@ -596,6 +754,7 @@ contract Gateway is IGatewayBase, IGatewayV1, IGatewayV2, IInitializable, IUpgra /// ``` /// function initialize(bytes calldata data) external virtual { + GatewayCoreStorage.transferOwnership(msg.sender); Initializer.initialize(data); } } diff --git a/contracts/src/Operators.sol b/contracts/src/Operators.sol new file mode 100644 index 000000000..e730ef0ea --- /dev/null +++ b/contracts/src/Operators.sol @@ -0,0 +1,54 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity 0.8.28; + +import {console2} from "forge-std/console2.sol"; +import {BeefyClient} from "./BeefyClient.sol"; +import {ScaleCodec} from "./utils/ScaleCodec.sol"; +import {OSubstrateTypes} from "./libraries/OSubstrateTypes.sol"; +import {MultiAddress, Ticket, Costs, ParaID} from "./v1/Types.sol"; + +import {IOGateway} from "./interfaces/IOGateway.sol"; + +library Operators { + error Operators__OperatorsLengthTooLong(); + error Operators__OperatorsKeysCannotBeEmpty(); + + uint16 private constant MAX_OPERATORS = 1000; + + function encodeOperatorsData(bytes32[] calldata operatorsKeys, uint48 epoch) + internal + returns (Ticket memory ticket) + { + if (operatorsKeys.length == 0) { + revert Operators__OperatorsKeysCannotBeEmpty(); + } + uint256 validatorsKeysLength = operatorsKeys.length; + + if (validatorsKeysLength > MAX_OPERATORS) { + revert Operators__OperatorsLengthTooLong(); + } + + // TODO: This is a type from Snowbridge, do we want our own simplified Ticket type? + ticket.dest = ParaID.wrap(0); + // TODO For now mock it to 0 + ticket.costs = Costs(0, 0); + + ticket.payload = OSubstrateTypes.EncodedOperatorsData( + abi.encodePacked(operatorsKeys), uint32(validatorsKeysLength), epoch + ); + emit IOGateway.OperatorsDataCreated(validatorsKeysLength, ticket.payload); + } +} diff --git a/contracts/src/interfaces/IMiddlewareBasic.sol b/contracts/src/interfaces/IMiddlewareBasic.sol new file mode 100644 index 000000000..46f418a40 --- /dev/null +++ b/contracts/src/interfaces/IMiddlewareBasic.sol @@ -0,0 +1,53 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity ^0.8.0; + +interface IMiddlewareBasic { + /** + * @notice Distribute rewards for a specific era contained in an epoch by providing a Merkle root, total points, total amount of tokens and the token address of the rewards. + * @param epoch network epoch of the middleware + * @param eraIndex era index of Starlight's rewards distribution + * @param totalPointsToken total amount of points for the reward distribution + * @param amount amount of tokens to distribute + * @param root Merkle root of the reward distribution + * @param tokenAddress The token address of the rewards + * @dev This function is called by the gateway only + * @dev Emit DistributeRewards event. + */ + function distributeRewards( + uint256 epoch, + uint256 eraIndex, + uint256 totalPointsToken, + uint256 amount, + bytes32 root, + address tokenAddress + ) external; + + /** + * @notice Slashes an operator's stake + * @dev Only the owner can call this function + * @dev This function first updates the stake cache for the target epoch + * @param epoch The epoch number + * @param operatorKey The operator key to slash + * @param percentage Percentage to slash, represented as parts per billion. + */ + function slash(uint48 epoch, bytes32 operatorKey, uint256 percentage) external; + /** + * @notice Determines which epoch a timestamp belongs to + * @param timestamp The timestamp to check + * @return epoch The corresponding epoch number + */ + function getEpochAtTs(uint48 timestamp) external view returns (uint48 epoch); +} diff --git a/contracts/src/interfaces/IOGateway.sol b/contracts/src/interfaces/IOGateway.sol new file mode 100644 index 000000000..09e54d492 --- /dev/null +++ b/contracts/src/interfaces/IOGateway.sol @@ -0,0 +1,94 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity ^0.8.0; + +import {ParaID, Command, ChannelID} from "../v1/Types.sol"; +import {IGatewayBase} from "./IGatewayBase.sol"; + +interface IOGateway is IGatewayBase { + error MiddlewareNotSet(); + + error EUnableToProcessRewardsB( + uint256 epoch, + uint256 eraIndex, + address tokenAddress, + uint256 totalPointsToken, + uint256 totalTokensInflated, + bytes32 rewardsRoot, + bytes errorBytes + ); + error EUnableToProcessRewardsS( + uint256 epoch, + uint256 eraIndex, + address tokenAddress, + uint256 totalPointsToken, + uint256 totalTokensInflated, + bytes32 rewardsRoot, + string errorString + ); + + // Emitted when operators data has been created + event OperatorsDataCreated(uint256 indexed validatorsCount, bytes payload); + + // Emitted when the middleware fails to apply an individual slash + event UnableToProcessIndividualSlashB( + bytes32 indexed operatorKey, uint256 slashFranction, uint256 indexed epoch, bytes error + ); + + // Emitted when the middleware fails to apply an individual slash + event UnableToProcessIndividualSlashS( + bytes32 indexed operatorKey, uint256 slashFranction, uint256 indexed epoch, string error + ); + + // Emitted when the middleware fails to apply the slash message + event UnableToProcessSlashMessageB(bytes error); + + // Emitted when the middleware fails to apply the slash message + event UnableToProcessSlashMessageS(string error); + + // Emitted when the middleware fails to apply the slash message + event UnableToProcessRewardsMessageB(bytes error); + + // Emitted when the middleware fails to apply the slash message + event UnableToProcessRewardsMessageS(string error); + + // Emitted when a non accepted command is received + event NotImplementedCommand(Command command); + + // Slash struct, used to decode slashes, which are identified by + // operatorKey to be slashed + // slashFraction to be applied as parts per billion + // epoch identifying when the slash happened + struct Slash { + bytes32 operatorKey; + uint256 slashFraction; + uint256 epoch; + } + + struct SlashParams { + uint256 eraIndex; + Slash[] slashes; + } + + function s_middleware() external view returns (address); + + function reportSlashes(bytes calldata data) external; + + function sendRewards(ChannelID channelID, bytes calldata data) external; + + function sendOperatorsData(bytes32[] calldata data, uint48 epoch) external; + + function setMiddleware(address middleware) external; +} diff --git a/contracts/src/libraries/OSubstrateTypes.sol b/contracts/src/libraries/OSubstrateTypes.sol new file mode 100644 index 000000000..6fb6445a2 --- /dev/null +++ b/contracts/src/libraries/OSubstrateTypes.sol @@ -0,0 +1,43 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity 0.8.28; + +import {ScaleCodec} from "../utils/ScaleCodec.sol"; +import {ParaID} from "../v1/Types.sol"; + +library OSubstrateTypes { + enum Message { + V0 + } + + enum OutboundCommandV1 { + ReceiveValidators + } + + function EncodedOperatorsData( + bytes memory encodedOperatorsKeys, + uint32 operatorsCount, + uint48 epoch + ) internal pure returns (bytes memory) { + return bytes.concat( + bytes4(0x70150038), + bytes1(uint8(Message.V0)), + bytes1(uint8(OutboundCommandV1.ReceiveValidators)), + ScaleCodec.encodeCompactU32(operatorsCount), + encodedOperatorsKeys, + ScaleCodec.encodeU64(uint64(epoch)) + ); + } +} diff --git a/contracts/src/storage/GatewayCoreStorage.sol b/contracts/src/storage/GatewayCoreStorage.sol new file mode 100644 index 000000000..6d52d6661 --- /dev/null +++ b/contracts/src/storage/GatewayCoreStorage.sol @@ -0,0 +1,71 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity 0.8.28; + +library GatewayCoreStorage { + // Emitted when owner of the gateway is changed. + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + // Emitted when the middleware contract address is changed by the owner. + event MiddlewareChanged(address indexed previousMiddleware, address indexed newMiddleware); + + error CantSetMiddlewareToZeroAddress(); + error CantSetMiddlewareToSameAddress(); + + struct Layout { + // Owner of the gateway for configuration purposes. + address owner; + // Address of the Symbiotic middleware to properly execute messages. + address middleware; + } + + bytes32 internal constant SLOT = keccak256("tanssi-bridge-relayer.gateway.core"); + + function layout() internal pure returns (Layout storage ptr) { + bytes32 slot = SLOT; + assembly { + ptr.slot := slot + } + } + + function transferOwnership(address newOwner) external { + Layout storage l = layout(); + address previousOwner = l.owner; + l.owner = newOwner; + emit OwnershipTransferred(previousOwner, newOwner); + } + + /// Changes the middleware address. + function setMiddleware(address middleware) external { + Layout storage l = layout(); + address oldMiddleware = l.middleware; + + if (middleware == address(0)) { + revert CantSetMiddlewareToZeroAddress(); + } + + if (middleware == oldMiddleware) { + revert CantSetMiddlewareToSameAddress(); + } + + l.middleware = middleware; + emit MiddlewareChanged(oldMiddleware, middleware); + } + + function s_middleware() external view returns (address) { + Layout storage l = layout(); + return l.middleware; + } +} diff --git a/contracts/src/upgrades/Gateway202502.sol b/contracts/src/upgrades/Gateway202502.sol new file mode 100644 index 000000000..ed475a567 --- /dev/null +++ b/contracts/src/upgrades/Gateway202502.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import "../Gateway.sol"; + +// New `Gateway` logic contract for the `GatewayProxy` deployed on mainnet +contract Gateway202502 is Gateway { + constructor(address beefyClient, address agentExecutor) Gateway(beefyClient, agentExecutor) {} + + // Override parent initializer to prevent re-initialization of storage. + function initialize(bytes memory) external override { + // Ensure that arbitrary users cannot initialize storage in this logic contract. + if (ERC1967.load() == address(0)) { + revert Unauthorized(); + } + + // Register native Ether + AssetsStorage.Layout storage assets = AssetsStorage.layout(); + TokenInfo storage tokenInfo = assets.tokenRegistry[address(0)]; + tokenInfo.isRegistered = true; + } +} diff --git a/contracts/src/upgrades/GatewayTanssi202506.sol b/contracts/src/upgrades/GatewayTanssi202506.sol new file mode 100644 index 000000000..7933f3d06 --- /dev/null +++ b/contracts/src/upgrades/GatewayTanssi202506.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import "../Gateway.sol"; + +// New `Gateway` logic contract for the `GatewayProxy` deployed on mainnet +contract GatewayTanssi202506 is Gateway { + constructor(address beefyClient, address agentExecutor) Gateway(beefyClient, agentExecutor) {} + + // Override parent initializer to prevent re-initialization of storage. + function initialize(bytes memory) external view override { + // Ensure that arbitrary users cannot initialize storage in this logic contract. + if (ERC1967.load() == address(0)) { + revert Unauthorized(); + } + } +} diff --git a/contracts/src/upgrades/GatewayTanssi202507.sol b/contracts/src/upgrades/GatewayTanssi202507.sol new file mode 100644 index 000000000..3e6472e3f --- /dev/null +++ b/contracts/src/upgrades/GatewayTanssi202507.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import "../Gateway.sol"; + +// New `Gateway` logic contract for the `GatewayProxy` deployed on mainnet +contract GatewayTanssi202507 is Gateway { + constructor(address beefyClient, address agentExecutor) Gateway(beefyClient, agentExecutor) {} + + // Override parent initializer to prevent re-initialization of storage. + function initialize(bytes memory) external view override { + // Ensure that arbitrary users cannot initialize storage in this logic contract. + if (ERC1967.load() == address(0)) { + revert Unauthorized(); + } + } +} diff --git a/contracts/src/upgrades/GatewayTanssi202509.sol b/contracts/src/upgrades/GatewayTanssi202509.sol new file mode 100644 index 000000000..7a991d7d3 --- /dev/null +++ b/contracts/src/upgrades/GatewayTanssi202509.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import "../Gateway.sol"; + +// New `Gateway` logic contract for the `GatewayProxy` deployed on mainnet +contract GatewayTanssi202509 is Gateway { + constructor(address beefyClient, address agentExecutor) Gateway(beefyClient, agentExecutor) {} + + // Override parent initializer to prevent re-initialization of storage. + function initialize(bytes memory) external override { + // Ensure that arbitrary users cannot initialize storage in this logic contract. + if (ERC1967.load() == address(0)) { + revert Unauthorized(); + } + + // register the address 0 token + AssetsStorage.Layout storage assets = AssetsStorage.layout(); + TokenInfo storage etherTokenInfo = assets.tokenRegistry[address(0)]; + etherTokenInfo.isRegistered = true; + } +} diff --git a/contracts/src/v1/Calls.sol b/contracts/src/v1/Calls.sol index 9dff1ded5..29feabc9f 100644 --- a/contracts/src/v1/Calls.sol +++ b/contracts/src/v1/Calls.sol @@ -29,6 +29,8 @@ import { import {IGatewayBase} from "../interfaces/IGatewayBase.sol"; import {IGatewayV1} from "./IGateway.sol"; import {UD60x18, ud60x18, convert} from "prb/math/src/UD60x18.sol"; +import {Operators} from "../Operators.sol"; +import {Constants} from "../Constants.sol"; /// @title Library for implementing Ethereum->Polkadot ERC20 transfers. library CallsV1 { @@ -176,6 +178,11 @@ library CallsV1 { return $.tokenAddressOf[tokenID]; } + function sendOperatorsData(bytes32[] calldata data, uint48 epoch) external { + Ticket memory ticket = Operators.encodeOperatorsData(data, epoch); + _submitOutboundToChannel(Constants.PRIMARY_GOVERNANCE_CHANNEL_ID, ticket.payload); + } + /* * Internal functions */ @@ -250,6 +257,26 @@ library CallsV1 { ); } + // Submit an outbound message to a specific channel. + // Doesn't handle fees. + function _submitOutboundToChannel(ChannelID channelID, bytes memory payload) internal { + Channel storage channel = Functions.ensureChannel(channelID); + + // Ensure outbound messaging is allowed + _ensureOutboundMessagingEnabled(channel); + + // Increase channel nonce + channel.outboundNonce = channel.outboundNonce + 1; + + // Generate a unique ID for this message + bytes32 messageID = keccak256(abi.encodePacked(channelID, channel.outboundNonce)); + + // Emit event for bridge + emit IGatewayV1.OutboundMessageAccepted( + channelID, channel.outboundNonce, messageID, payload + ); + } + function isTokenRegistered(address token) external view returns (bool) { return AssetsStorage.layout().tokenRegistry[token].isRegistered; } diff --git a/contracts/src/v1/Types.sol b/contracts/src/v1/Types.sol index 244e465c2..ee79f1636 100644 --- a/contracts/src/v1/Types.sol +++ b/contracts/src/v1/Types.sol @@ -2,8 +2,13 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.28; +import { + MultiAddress, + multiAddressFromUint32, + multiAddressFromBytes32, + multiAddressFromBytes20 +} from "./MultiAddress.sol"; import {TokenInfo, OperatingMode} from "../types/Common.sol"; -import {MultiAddress} from "./MultiAddress.sol"; import {UD60x18} from "prb/math/src/UD60x18.sol"; type ParaID is uint32; @@ -80,7 +85,31 @@ enum Command { SetPricingParameters, UnlockNativeToken, RegisterForeignToken, - MintForeignToken + MintForeignToken, + /// @dev Below enums are reserved in case upstream snowbridge adds more commands + Reserved12, + Reserved13, + Reserved14, + Reserved15, + Reserved16, + Reserved17, + Reserved18, + Reserved19, + Reserved20, + Reserved21, + Reserved22, + Reserved23, + Reserved24, + Reserved25, + Reserved26, + Reserved27, + Reserved28, + Reserved29, + Reserved30, + Reserved31, + Test, + ReportRewards, + ReportSlashes } // Deprecated diff --git a/contracts/src/v2/Types.sol b/contracts/src/v2/Types.sol index 08c3b4a5e..8716ab0db 100644 --- a/contracts/src/v2/Types.sol +++ b/contracts/src/v2/Types.sol @@ -36,6 +36,14 @@ library CommandKind { uint8 constant MintForeignToken = 4; // Call an arbitrary solidity contract uint8 constant CallContract = 5; + + // Test command + uint8 constant Test = 25; + // TODO this needs to be adapted to new meta middleware once needed + // Distribute rewards to middleware + uint8 constant ReportRewards = 26; + // Slashes operators to the middleware + uint8 constant ReportSlashes = 27; } // Payload for outbound messages destined for Polkadot diff --git a/contracts/test/GatewayV1.t.sol b/contracts/test/GatewayV1.t.sol index 6027291f8..aed9fd10e 100644 --- a/contracts/test/GatewayV1.t.sol +++ b/contracts/test/GatewayV1.t.sol @@ -176,8 +176,7 @@ contract GatewayV1Test is Test { ) public pure returns (Command, bytes memory) { bytes memory payload = abi.encode(token_, recipient, amount); AgentExecuteParams memory params = AgentExecuteParams({ - agentID: agentID, - payload: abi.encode(AgentExecuteCommand.TransferToken, payload) + agentID: agentID, payload: abi.encode(AgentExecuteCommand.TransferToken, payload) }); return (Command.AgentExecute, abi.encode(params)); } @@ -189,10 +188,7 @@ contract GatewayV1Test is Test { uint128 amount ) public pure returns (Command, bytes memory) { UnlockNativeTokenParams memory params = UnlockNativeTokenParams({ - agentID: agentID, - token: _token, - recipient: recipient, - amount: amount + agentID: agentID, token: _token, recipient: recipient, amount: amount }); return (Command.UnlockNativeToken, abi.encode(params)); } @@ -249,20 +245,21 @@ contract GatewayV1Test is Test { emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); assertEq(token.balanceOf(assetHubAgent), 0); assertEq(token.balanceOf(recipient), amount); @@ -290,20 +287,21 @@ contract GatewayV1Test is Test { emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); assertEq(token.balanceOf(assetHubAgent), 0); assertEq(token.balanceOf(recipient), amount); @@ -326,20 +324,21 @@ contract GatewayV1Test is Test { emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); assertEq(assetHubAgent.balance, 0); assertEq(recipient.balance, amount); @@ -360,20 +359,21 @@ contract GatewayV1Test is Test { emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); assertEq(assetHubAgent.balance, 0); assertEq(recipient.balance, amount); @@ -387,38 +387,40 @@ contract GatewayV1Test is Test { makeUnlockTokenCommand(assetHubAgentID, address(0), recipient, amount); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); // try to replay the message vm.expectRevert(IGatewayBase.InvalidNonce.selector); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); } function testSubmitFailInvalidChannel() public { @@ -430,20 +432,21 @@ contract GatewayV1Test is Test { vm.expectRevert(IGatewayV1.ChannelDoesNotExist.selector); hoax(relayer); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - ParaID.wrap(42).into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + ParaID.wrap(42).into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); } function testSubmitFailInvalidProof() public { @@ -457,20 +460,21 @@ contract GatewayV1Test is Test { vm.expectRevert(IGatewayBase.InvalidProof.selector); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); } /** @@ -510,20 +514,21 @@ contract GatewayV1Test is Test { uint256 agentBalanceBefore = address(assetHubAgent).balance; uint256 startGas = gasleft(); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); uint256 endGas = gasleft(); uint256 estimatedActualRefundAmount = (startGas - endGas) * tx.gasprice; assertLt(estimatedActualRefundAmount, maxRefund); @@ -552,20 +557,21 @@ contract GatewayV1Test is Test { makeUnlockTokenCommand(assetHubAgentID, address(0), recipient, amount); hoax(relayer, 1 ether); - IGatewayV1(address(gateway)).submitV1( - InboundMessage( - assetHubParaID.into(), - 1, - command, - params, - maxDispatchGas, - maxRefund, - reward, - messageID - ), - proof, - makeMockProof() - ); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); assertEq(address(assetHubAgent).balance, 0 ether); assertEq(relayer.balance, 1 ether); @@ -753,9 +759,7 @@ contract GatewayV1Test is Test { MockGatewayV2 newLogic = new MockGatewayV2(); UpgradeParams memory params = UpgradeParams({ - impl: address(newLogic), - implCodeHash: bytes32(0), - initParams: abi.encode(42) + impl: address(newLogic), implCodeHash: bytes32(0), initParams: abi.encode(42) }); vm.expectRevert(IUpgradable.InvalidCodeHash.selector); @@ -906,9 +910,10 @@ contract GatewayV1Test is Test { // Let gateway lock up to 1 tokens token.approve(address(gateway), 1); - MockGateway(address(gateway)).v1_handleSetOperatingMode_public( - abi.encode(SetOperatingModeParams({mode: OperatingMode.RejectingOutboundMessages})) - ); + MockGateway(address(gateway)) + .v1_handleSetOperatingMode_public( + abi.encode(SetOperatingModeParams({mode: OperatingMode.RejectingOutboundMessages})) + ); OperatingMode mode = IGatewayV1(address(gateway)).operatingMode(); assertEq(uint256(mode), 1); @@ -972,15 +977,16 @@ contract GatewayV1Test is Test { uint256 fee = IGatewayV1(address(gateway)).quoteRegisterTokenFee(); assertEq(fee, 5_000_000_000_000_000); // Double the assetHubCreateAssetFee - MockGateway(address(gateway)).v1_handleSetTokenTransferFees_public( - abi.encode( - SetTokenTransferFeesParams({ - assetHubCreateAssetFee: createTokenFee * 2, - registerTokenFee: registerTokenFee, - assetHubReserveTransferFee: sendTokenFee * 3 - }) - ) - ); + MockGateway(address(gateway)) + .v1_handleSetTokenTransferFees_public( + abi.encode( + SetTokenTransferFeesParams({ + assetHubCreateAssetFee: createTokenFee * 2, + registerTokenFee: registerTokenFee, + assetHubReserveTransferFee: sendTokenFee * 3 + }) + ) + ); fee = IGatewayV1(address(gateway)).quoteRegisterTokenFee(); // since deliveryCost not changed, so the total fee increased only by 50% assertEq(fee, 7_500_000_000_000_000); @@ -999,15 +1005,16 @@ contract GatewayV1Test is Test { uint256 fee = IGatewayV1(address(gateway)).quoteRegisterTokenFee(); assertEq(fee, 5_000_000_000_000_000); // Double both the exchangeRate and multiplier. Should lead to an 4x fee increase - MockGateway(address(gateway)).v1_handleSetPricingParameters_public( - abi.encode( - SetPricingParametersParams({ - exchangeRate: exchangeRate.mul(convert(2)), - multiplier: multiplier.mul(convert(2)), - deliveryCost: outboundFee - }) - ) - ); + MockGateway(address(gateway)) + .v1_handleSetPricingParameters_public( + abi.encode( + SetPricingParametersParams({ + exchangeRate: exchangeRate.mul(convert(2)), + multiplier: multiplier.mul(convert(2)), + deliveryCost: outboundFee + }) + ) + ); // Should expect 4x fee increase fee = IGatewayV1(address(gateway)).quoteRegisterTokenFee(); assertEq(fee, 20_000_000_000_000_001); @@ -1043,9 +1050,8 @@ contract GatewayV1Test is Test { IGatewayV1(address(gateway)).registerToken{value: fee}(address(token)); vm.expectRevert(IGatewayBase.InvalidDestinationFee.selector); - IGatewayV1(address(gateway)).quoteSendTokenFee( - address(token), destPara, maxDestinationFee + 1 - ); + IGatewayV1(address(gateway)) + .quoteSendTokenFee(address(token), destPara, maxDestinationFee + 1); vm.expectRevert(IGatewayBase.InvalidDestinationFee.selector); IGatewayV1(address(gateway)).sendToken{value: fee}( @@ -1057,10 +1063,7 @@ contract GatewayV1Test is Test { token.transfer(address(assetHubAgent), 200); UnlockNativeTokenParams memory params = UnlockNativeTokenParams({ - agentID: assetHubAgentID, - token: address(token), - recipient: account2, - amount: 10 + agentID: assetHubAgentID, token: address(token), recipient: account2, amount: 10 }); bytes memory encodedParams = abi.encode(params); @@ -1069,10 +1072,7 @@ contract GatewayV1Test is Test { function testRegisterForeignToken() public { RegisterForeignTokenParams memory params = RegisterForeignTokenParams({ - foreignTokenID: dotTokenID, - name: "DOT", - symbol: "DOT", - decimals: 10 + foreignTokenID: dotTokenID, name: "DOT", symbol: "DOT", decimals: 10 }); vm.expectEmit(true, true, false, false); @@ -1085,10 +1085,7 @@ contract GatewayV1Test is Test { testRegisterForeignToken(); RegisterForeignTokenParams memory params = RegisterForeignTokenParams({ - foreignTokenID: dotTokenID, - name: "DOT", - symbol: "DOT", - decimals: 10 + foreignTokenID: dotTokenID, name: "DOT", symbol: "DOT", decimals: 10 }); vm.expectRevert(IGatewayBase.TokenAlreadyRegistered.selector); @@ -1102,17 +1099,14 @@ contract GatewayV1Test is Test { uint128 amount = 1000; MintForeignTokenParams memory params = MintForeignTokenParams({ - foreignTokenID: bytes32(uint256(1)), - recipient: account1, - amount: amount + foreignTokenID: bytes32(uint256(1)), recipient: account1, amount: amount }); vm.expectEmit(true, true, false, false); emit Transfer(address(0), account1, 1000); - MockGateway(address(gateway)).v1_handleMintForeignToken_public( - assetHubParaID.into(), abi.encode(params) - ); + MockGateway(address(gateway)) + .v1_handleMintForeignToken_public(assetHubParaID.into(), abi.encode(params)); address dotToken = MockGateway(address(gateway)).tokenAddressOf(dotTokenID); uint256 balance = Token(dotToken).balanceOf(account1); @@ -1122,30 +1116,24 @@ contract GatewayV1Test is Test { function testMintNotRegisteredTokenWillFail() public { MintForeignTokenParams memory params = MintForeignTokenParams({ - foreignTokenID: bytes32(uint256(1)), - recipient: account1, - amount: 1000 + foreignTokenID: bytes32(uint256(1)), recipient: account1, amount: 1000 }); vm.expectRevert(IGatewayBase.TokenNotRegistered.selector); - MockGateway(address(gateway)).v1_handleMintForeignToken_public( - ParaID.wrap(1000).into(), abi.encode(params) - ); + MockGateway(address(gateway)) + .v1_handleMintForeignToken_public(ParaID.wrap(1000).into(), abi.encode(params)); } function testMintFromParachainOtherThanAssetHubWillFail() public { MintForeignTokenParams memory params = MintForeignTokenParams({ - foreignTokenID: bytes32(uint256(1)), - recipient: account1, - amount: 1000 + foreignTokenID: bytes32(uint256(1)), recipient: account1, amount: 1000 }); vm.expectRevert(IGatewayBase.Unauthorized.selector); - MockGateway(address(gateway)).v1_handleMintForeignToken_public( - ParaID.wrap(2002).into(), abi.encode(params) - ); + MockGateway(address(gateway)) + .v1_handleMintForeignToken_public(ParaID.wrap(2002).into(), abi.encode(params)); } function testSendRelayTokenToAssetHubWithAddress32() public { @@ -1252,7 +1240,8 @@ contract GatewayV1Test is Test { AgentExecuteParams memory params = AgentExecuteParams({ agentID: assetHubAgentID, payload: abi.encode( - AgentExecuteCommand.TransferToken, abi.encode(address(token), address(account2), 10) + AgentExecuteCommand.TransferToken, + abi.encode(address(token), address(account2), 10) ) }); diff --git a/contracts/test/data/beefy-final-bitfield-0.json b/contracts/test/data/beefy-final-bitfield-0.json index 83d686da8..ead3ce662 100644 --- a/contracts/test/data/beefy-final-bitfield-0.json +++ b/contracts/test/data/beefy-final-bitfield-0.json @@ -1,7 +1,7 @@ { "final": { "finalBitField": [ - 3618516597240194183335682014798479784171758623595086523846459157562028721232, + "3618516597240194183335682014798479784171758623595086523846459157562028721232", 4415226380304 ], "finalBitFieldRaw": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000208000200304020000800900820002000004000800008010000010010c00004500000000000000000000000000000000000000000000000000000040400000010" diff --git a/contracts/test/data/beefy-final-bitfield-3.json b/contracts/test/data/beefy-final-bitfield-3.json index 2ad7a7243..290d4f387 100644 --- a/contracts/test/data/beefy-final-bitfield-3.json +++ b/contracts/test/data/beefy-final-bitfield-3.json @@ -1,7 +1,7 @@ { "final": { "finalBitField": [ - 3618516597240194183335683517222162960339958537141550881213932039047770801232, + "3618516597240194183335683517222162960339958537141550881213932039047770801232", 4415226380306 ], "finalBitFieldRaw": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000208000200304020000800940c20002000004000820008010000010010c00004500000000000000000000000000000000000000000000000000000040400000012" diff --git a/contracts/test/override_test/Gateway.t.sol b/contracts/test/override_test/Gateway.t.sol new file mode 100644 index 000000000..80a7532b9 --- /dev/null +++ b/contracts/test/override_test/Gateway.t.sol @@ -0,0 +1,802 @@ +//SPDX-License-Identifier: GPL-3.0-or-later + +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. +// Tanssi is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// Tanssi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with Tanssi. If not, see +pragma solidity 0.8.28; + +import {Test, console2, Vm} from "forge-std/Test.sol"; +import {IGatewayV1, IGatewayV2} from "../../src/Types.sol"; +import { + AgentExecuteCommand, + InboundMessage, + OperatingMode, + ParaID, + ChannelID, + Command, + multiAddressFromBytes32, + multiAddressFromBytes20, + RegisterForeignTokenParams, + SetOperatingModeParams +} from "../../src/v1/Types.sol"; + +import {IGatewayBase} from "../../src/interfaces/IGatewayBase.sol"; +import {IMiddlewareBasic} from "../../src/interfaces/IMiddlewareBasic.sol"; +import {MockGateway} from "../mocks/MockGateway.sol"; +import {OperatingMode, ParaID, Command} from "../../src/v1/Types.sol"; +import {GatewayProxy} from "../../src/GatewayProxy.sol"; +import {MultiAddress} from "../../src/v1/MultiAddress.sol"; +import {AgentExecutor} from "../../src/AgentExecutor.sol"; +import {Verification} from "../../src/Verification.sol"; +import {Initializer} from "../../src/Initializer.sol"; +import {Strings} from "openzeppelin/utils/Strings.sol"; + +import {Gateway} from "../../src/Gateway.sol"; +import {IOGateway} from "../../src/interfaces/IOGateway.sol"; +import {Operators} from "../../src/Operators.sol"; +import {Token} from "../../src/Token.sol"; +//NEW +import {WETH9} from "canonical-weth/WETH9.sol"; +import {UD60x18, ud60x18, convert} from "prb/math/src/UD60x18.sol"; +import {GatewayCoreStorage} from "../../src/storage/GatewayCoreStorage.sol"; + +contract GatewayV1Test is Test { + // Emitted when token minted/burnt/transfered + event Transfer(address indexed from, address indexed to, uint256 value); + + ParaID public bridgeHubParaID = ParaID.wrap(1013); + bytes32 public bridgeHubAgentID = + 0x03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314; + address public bridgeHubAgent; + + ParaID public assetHubParaID = ParaID.wrap(1000); + bytes32 public assetHubAgentID = + 0x81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79; + address public assetHubAgent; + + address public relayer; + + bytes32[] public proof = + [bytes32(0x2f9ee6cfdf244060dc28aa46347c5219e303fc95062dd672b4e406ca5c29764b)]; + bytes public parachainHeaderProof = bytes("validProof"); + + MockGateway public gatewayLogic; + GatewayProxy public gateway; + + WETH9 public token; + + address public account1; + address public account2; + address public middleware = makeAddr("middleware"); + + uint64 public maxDispatchGas = 500_000; + uint256 public maxRefund = 1 ether; + uint256 public reward = 1 ether; + bytes32 public messageID = keccak256("cabbage"); + + // remote fees in DOT + uint128 public outboundFee = 1e10; + uint128 public registerTokenFee = 0; + uint128 public sendTokenFee = 1e10; + uint128 public createTokenFee = 1e10; + uint128 public maxDestinationFee = 1e11; + + MultiAddress public recipientAddress32; + MultiAddress public recipientAddress20; + + // For DOT + uint8 public foreignTokenDecimals = 10; + + // ETH/DOT exchange rate + UD60x18 public exchangeRate = ud60x18(0.0025e18); + UD60x18 public multiplier = ud60x18(1e18); + + // tokenID for DOT + bytes32 public dotTokenID; + + uint256 public constant SLASH_FRACTION = 500_000; + uint256 public constant ONE_DAY = 86_400; + + ChannelID internal constant PRIMARY_GOVERNANCE_CHANNEL_ID = + ChannelID.wrap(bytes32(uint256(1))); + ChannelID internal constant SECONDARY_GOVERNANCE_CHANNEL_ID = + ChannelID.wrap(bytes32(uint256(2))); + + // It's generated using VALIDATORS_DATA using scaleCodec. See OSubstrateTypes.EncodedOperatorsData in OSubstrateTypes.sol + bytes private constant FINAL_VALIDATORS_PAYLOAD = + hex"7015003800000cd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe228eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480100000000000000"; + + bytes32[] private VALIDATORS_DATA = [ + bytes32(0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d), + bytes32(0x90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22), + bytes32(0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48) + ]; + + // Test vector generated by: https://github.com/moondance-labs/tanssi/blob/242196324a37ac0020a7c7955bffe09670f63751/primitives/bridge/src/tests.rs#L84 + bytes private constant TEST_VECTOR_SLASH_DATA = + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002A000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030404040404040404040404040404040404040404040404040404040404040404000000000000000000000000000000000000000000000000000000000000138800000000000000000000000000000000000000000000000000000000000001F405050505050505050505050505050505050505050505050505050505050505050000000000000000000000000000000000000000000000000000000000000FA0000000000000000000000000000000000000000000000000000000000000019006060606060606060606060606060606060606060606060606060606060606060000000000000000000000000000000000000000000000000000000000000BB8000000000000000000000000000000000000000000000000000000000000012C"; + + bytes private constant TEST_VECTOR_REWARDS_DATA = + hex"00000000000000000000000000000000000000000000000000000000075BCD15000000000000000000000000000000000000000000000000000000000000002A00000000000000000000000000000000000000000000000000007048860DDF79000000000000000000000000000000000000000000000000000000E5F4C8F3CAb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e40101010101010101010101010101010101010101010101010101010101010101"; + + function setUp() public { + AgentExecutor executor = new AgentExecutor(); + gatewayLogic = new MockGateway(address(0), address(executor)); + + Initializer.Config memory config = Initializer.Config({ + mode: OperatingMode.Normal, + deliveryCost: outboundFee, + registerTokenFee: registerTokenFee, + assetHubCreateAssetFee: createTokenFee, + assetHubReserveTransferFee: sendTokenFee, + exchangeRate: exchangeRate, + multiplier: multiplier, + foreignTokenDecimals: foreignTokenDecimals, + maxDestinationFee: maxDestinationFee + }); + + gateway = new GatewayProxy(address(gatewayLogic), abi.encode(config)); + MockGateway(address(gateway)).setCommitmentsAreVerified(true); + + SetOperatingModeParams memory params = SetOperatingModeParams({mode: OperatingMode.Normal}); + MockGateway(address(gateway)).v1_handleSetOperatingMode_public(abi.encode(params)); + + bridgeHubAgent = IGatewayV1(address(gateway)).agentOf(bridgeHubAgentID); + assetHubAgent = IGatewayV1(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}(); + + recipientAddress32 = multiAddressFromBytes32(keccak256("recipient")); + recipientAddress20 = multiAddressFromBytes20(bytes20(keccak256("recipient"))); + + dotTokenID = bytes32(uint256(1)); + } + + function _makeReportSlashesCommand(uint256 slashFraction) + public + pure + returns (Command, bytes memory) + { + IOGateway.Slash[] memory slashes = new IOGateway.Slash[](1); + slashes[0] = IOGateway.Slash({ + operatorKey: bytes32(uint256(1)), slashFraction: slashFraction, epoch: 1 + }); + uint256 eraIndex = 1; + return ( + Command.ReportSlashes, + abi.encode(IOGateway.SlashParams({eraIndex: eraIndex, slashes: slashes})) + ); + } + + function _makeReportRewardsCommand() public returns (Command, bytes memory, address) { + uint256 epoch = 0; + uint256 eraIndex = 1; + uint256 totalPointsToken = 1 ether; + uint256 tokensInflatedToken = 1 ether; + bytes32 rewardsRoot = bytes32(uint256(1)); + bytes32 foreignTokenId = bytes32(uint256(1)); + + RegisterForeignTokenParams memory params = RegisterForeignTokenParams({ + foreignTokenID: foreignTokenId, name: "Test", symbol: "TST", decimals: 10 + }); + + vm.expectEmit(true, true, false, false); + emit IGatewayBase.ForeignTokenRegistered(foreignTokenId, address(0)); + MockGateway(address(gateway)).v1_handleRegisterForeignToken_public(abi.encode(params)); + + address tokenAddress = MockGateway(address(gateway)).tokenAddressOf(foreignTokenId); + + return ( + Command.ReportRewards, + abi.encode( + epoch, eraIndex, totalPointsToken, tokensInflatedToken, rewardsRoot, foreignTokenId + ), + tokenAddress + ); + } + + 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 + }); + } + + function createLongOperatorsData() public view returns (bytes32[] memory) { + bytes32[] memory result = new bytes32[](1001); + + for (uint256 i = 0; i <= 1000; i++) { + result[i] = VALIDATORS_DATA[i % 3]; + } + + return result; + } + + function testSendOperatorsData() public { + // FINAL_VALIDATORS_PAYLOAD has been encoded with epoch 1. + uint48 epoch = 1; + IOGateway(address(gateway)).setMiddleware(middleware); + // Create mock agent and paraID + vm.prank(middleware); + vm.expectEmit(true, false, false, true); + emit IGatewayV1.OutboundMessageAccepted( + PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, FINAL_VALIDATORS_PAYLOAD + ); + + IOGateway(address(gateway)).sendOperatorsData(VALIDATORS_DATA, epoch); + } + + function testShouldNotSendOperatorsDataBecauseOperatorsTooLong() public { + bytes32[] memory longOperatorsData = createLongOperatorsData(); + uint48 epoch = 42; + IOGateway(address(gateway)).setMiddleware(middleware); + vm.prank(middleware); + vm.expectRevert(Operators.Operators__OperatorsLengthTooLong.selector); + IOGateway(address(gateway)).sendOperatorsData(longOperatorsData, epoch); + } + + function testSendOperatorsDataWith50Entries() public { + string memory root = vm.projectRoot(); + string memory path = + string.concat(root, "/test/snowbridge-data/test_vector_message_validator_50.json"); + string memory json = vm.readFile(path); + + // Get payload + bytes memory final_payload = vm.parseJsonBytes(json, "$.payload"); + + // Get accounts array + bytes32[] memory accounts = abi.decode(vm.parseJson(json, "$.accounts"), (bytes32[])); + + uint48 epoch = abi.decode(vm.parseJson(json, "$.epoch"), (uint48)); + + IOGateway(address(gateway)).setMiddleware(middleware); + + vm.prank(middleware); + vm.expectEmit(true, false, false, true); + emit IGatewayV1.OutboundMessageAccepted( + PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, final_payload + ); + + IOGateway(address(gateway)).sendOperatorsData(accounts, epoch); + } + + function testSendOperatorsDataWith400Entries() public { + string memory root = vm.projectRoot(); + string memory path = + string.concat(root, "/test/snowbridge-data/test_vector_message_validator_400.json"); + string memory json = vm.readFile(path); + + // Get payload + bytes memory final_payload = vm.parseJsonBytes(json, "$.payload"); + + // Get accounts array + bytes32[] memory accounts = abi.decode(vm.parseJson(json, "$.accounts"), (bytes32[])); + uint48 epoch = abi.decode(vm.parseJson(json, "$.epoch"), (uint48)); + + IOGateway(address(gateway)).setMiddleware(middleware); + + vm.prank(middleware); + vm.expectEmit(true, false, false, true); + emit IGatewayV1.OutboundMessageAccepted( + PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, final_payload + ); + + IOGateway(address(gateway)).sendOperatorsData(accounts, epoch); + } + + function testSendOperatorsDataWith1000Entries() public { + string memory root = vm.projectRoot(); + string memory path = + string.concat(root, "/test/snowbridge-data/test_vector_message_validator_1000.json"); + string memory json = vm.readFile(path); + + // Get payload + bytes memory final_payload = vm.parseJsonBytes(json, "$.payload"); + + // Get accounts array + bytes32[] memory accounts = abi.decode(vm.parseJson(json, "$.accounts"), (bytes32[])); + uint48 epoch = abi.decode(vm.parseJson(json, "$.epoch"), (uint48)); + + IOGateway(address(gateway)).setMiddleware(middleware); + + vm.prank(middleware); + vm.expectEmit(true, false, false, true); + emit IGatewayV1.OutboundMessageAccepted( + PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, final_payload + ); + + IOGateway(address(gateway)).sendOperatorsData(accounts, epoch); + } + + function testOwnerCanChangeMiddleware() public { + vm.expectEmit(true, true, false, false); + emit GatewayCoreStorage.MiddlewareChanged( + address(0), 0x0123456789012345678901234567890123456789 + ); + + IOGateway(address(gateway)).setMiddleware(0x0123456789012345678901234567890123456789); + + require( + IOGateway(address(gateway)).s_middleware() + == 0x0123456789012345678901234567890123456789 + ); + } + + function testNonOwnerCantChangeMiddleware() public { + address notOwner = makeAddr("notOwner"); + vm.prank(notOwner); + vm.expectRevert(abi.encodeWithSelector(IGatewayBase.Unauthorized.selector)); + IOGateway(address(gateway)).setMiddleware(0x9876543210987654321098765432109876543210); + } + + function testDecodeSlashes() public { + uint256 eraIndex = 42; + IOGateway.Slash[] memory slashes = new IOGateway.Slash[](3); + bytes32 alice = 0x0404040404040404040404040404040404040404040404040404040404040404; + bytes32 bob = 0x0505050505050505050505050505050505050505050505050505050505050505; + bytes32 charlie = 0x0606060606060606060606060606060606060606060606060606060606060606; + + slashes[0] = IOGateway.Slash({operatorKey: alice, slashFraction: 5000, epoch: 500}); + slashes[1] = IOGateway.Slash({operatorKey: bob, slashFraction: 4000, epoch: 400}); + slashes[2] = IOGateway.Slash({operatorKey: charlie, slashFraction: 3000, epoch: 300}); + + assertEq( + abi.encode(IOGateway.SlashParams({eraIndex: eraIndex, slashes: slashes})), + TEST_VECTOR_SLASH_DATA + ); + } + + // middleware not set, should not be able to process slash + function testSubmitSlashesWithoutMiddleware() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params) = _makeReportSlashesCommand(SLASH_FRACTION); + + vm.expectEmit(true, true, true, true); + emit IOGateway.UnableToProcessSlashMessageB(abi.encodeWithSelector( + IOGateway.MiddlewareNotSet.selector + )); + // Expect the gateway to emit `InboundMessageDispatched` + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, false); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } + + // middleware set, but not complying with the interface, should not process slash + function testSubmitSlashesWithMiddlewareNotComplyingInterface() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params) = _makeReportSlashesCommand(SLASH_FRACTION); + + IOGateway(address(gateway)).setMiddleware(0x0123456789012345678901234567890123456789); + + bytes memory empty; + // Expect the gateway to emit `InboundMessageDispatched` + // For some reason when you are loading an address not complying an interface, you get an empty message + // It still serves us to know that this is the reason + vm.expectEmit(true, true, true, true); + emit IOGateway.UnableToProcessSlashMessageB(empty); + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, false); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } + + // middleware set, complying interface but slash reverts + function testSubmitSlashesWithMiddlewareComplyingInterfaceAndSlashRevert() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params) = _makeReportSlashesCommand(SLASH_FRACTION); + + bytes memory expectedError = bytes("no process slash"); + + // We mock the call so that it reverts + vm.mockCallRevert( + address(middleware), + abi.encodeWithSelector(IMiddlewareBasic.slash.selector), + "no process slash" + ); + + IOGateway(address(gateway)).setMiddleware(address(middleware)); + + IOGateway.Slash memory expectedSlash = IOGateway.Slash({ + operatorKey: bytes32(uint256(1)), slashFraction: SLASH_FRACTION, epoch: 1 + }); + + vm.expectEmit(true, true, true, true); + emit IOGateway.UnableToProcessIndividualSlashB( + expectedSlash.operatorKey, + expectedSlash.slashFraction, + expectedSlash.epoch, + expectedError + ); + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } + + // middleware set, complying interface and slash processed + function testSubmitSlashesWithMiddlewareComplyingInterfaceAndSlashProcessed() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params) = _makeReportSlashesCommand(SLASH_FRACTION); + + // We mock the call so that it does not revert + vm.mockCall( + address(middleware), + abi.encodeWithSelector(IMiddlewareBasic.slash.selector), + abi.encode(10) + ); + + IOGateway(address(gateway)).setMiddleware(address(middleware)); + + // Since we are asserting all fields, the last one is a true, therefore meaning + // that the dispatch went through correctly + + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); + + hoax(relayer, 1 ether); + vm.recordLogs(); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + + Vm.Log[] memory entries = vm.getRecordedLogs(); + // We assert none of the slash error events has been emitted + for (uint256 i = 0; i < entries.length; i++) { + assertNotEq(entries[i].topics[0], IOGateway.UnableToProcessIndividualSlashB.selector); + assertNotEq(entries[i].topics[0], IOGateway.UnableToProcessIndividualSlashS.selector); + } + } + + function testDecodeRewards() public { + uint256 epoch = 123_456_789; + uint256 eraIndex = 42; + uint256 totalPointsToken = 123_456_789_012_345; + uint256 tokensInflatedToken = 987_654_321_098; + bytes32 rewardsRoot = 0xb6e16d27ac5ab427a7f68900ac5559ce272dc6c37c82b3e052246c82244c50e4; + bytes32 foreignTokenId = 0x0101010101010101010101010101010101010101010101010101010101010101; + + assertEq( + abi.encode( + epoch, eraIndex, totalPointsToken, tokensInflatedToken, rewardsRoot, foreignTokenId + ), + TEST_VECTOR_REWARDS_DATA + ); + } + + function testSubmitRewards() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params, address tokenAddress) = _makeReportRewardsCommand(); + + // We mock the call so that it does not revert + vm.mockCall( + address(middleware), + abi.encodeWithSelector(IMiddlewareBasic.distributeRewards.selector), + abi.encode(true) + ); + + IOGateway(address(gateway)).setMiddleware(address(middleware)); + + // Expect the gateway to emit `InboundMessageDispatched` + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + + assert(Token(tokenAddress).balanceOf(address(middleware)) > 0); + } + + function testSubmitRewardsWithoutMiddleware() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params, address tokenAddress) = _makeReportRewardsCommand(); + + vm.expectEmit(true, true, true, true); + emit IOGateway.UnableToProcessRewardsMessageB(abi.encodeWithSelector( + IOGateway.MiddlewareNotSet.selector + )); + // Expect the gateway to emit `InboundMessageDispatched` + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, false); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } + + // middleware set, but not complying with the interface, should not process rewards + function testSubmitRewardsWithMiddlewareNotComplyingInterface() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params, address tokenAddress) = _makeReportRewardsCommand(); + + IOGateway(address(gateway)).setMiddleware(0x0123456789012345678901234567890123456789); + + bytes memory empty; + vm.expectEmit(true, true, true, true); + emit IOGateway.UnableToProcessRewardsMessageB(empty); + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, false); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } + + // middleware set, complying interface but rewards reverts + function testSubmitRewardsWithMiddlewareComplyingInterfaceAndRewardsRevert() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params, address tokenAddress) = _makeReportRewardsCommand(); + + bytes memory expectedError = bytes("can't process rewards"); //This should actually come from IODefaultOperatorRewards + + // We mock the call so that it reverts + vm.mockCallRevert( + address(middleware), + abi.encodeWithSelector(IMiddlewareBasic.distributeRewards.selector), + "can't process rewards" + ); + + IOGateway(address(gateway)).setMiddleware(address(middleware)); + + uint256 expectedEpoch = 0; + uint256 expectedEraIndex = 1; + uint256 expectedTotalPointsToken = 1 ether; + uint256 expectedTotalTokensInflated = 1 ether; + bytes32 expectedRewardsRoot = bytes32(uint256(1)); + bytes32 expectedForeignTokenId = bytes32(uint256(1)); + + address expectedTokenAddress = + MockGateway(address(gateway)).tokenAddressOf(expectedForeignTokenId); + bytes memory expectedBytes = abi.encodeWithSelector( + IOGateway.EUnableToProcessRewardsB.selector, + expectedEpoch, + expectedEraIndex, + expectedTokenAddress, + expectedTotalPointsToken, + expectedTotalTokensInflated, + expectedRewardsRoot, + expectedError + ); + + vm.expectEmit(true, true, true, true); + emit IOGateway.UnableToProcessRewardsMessageB(expectedBytes); + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, false); + + hoax(relayer, 1 ether); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } + + // middleware set, complying interface and rewards processed + function testSubmitRewardsWithMiddlewareComplyingInterfaceAndRewardsProcessed() public { + deal(assetHubAgent, 50 ether); + + (Command command, bytes memory params, address tokenAddress) = _makeReportRewardsCommand(); + + // We mock the call so that it does not revert + vm.mockCall( + address(middleware), + abi.encodeWithSelector(IMiddlewareBasic.distributeRewards.selector), + abi.encode(true) + ); + + IOGateway(address(gateway)).setMiddleware(address(middleware)); + + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, true); + + hoax(relayer, 1 ether); + vm.recordLogs(); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + params, + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + + Vm.Log[] memory entries = vm.getRecordedLogs(); + // We assert none of the rewards error events has been emitted + for (uint256 i = 0; i < entries.length; i++) { + assertNotEq(entries[i].topics[0], IOGateway.UnableToProcessRewardsMessageB.selector); + assertNotEq(entries[i].topics[0], IOGateway.UnableToProcessRewardsMessageS.selector); + } + } + + // middleware set, complying interface and rewards processed + function testCommandUnrecognizedShouldEmitNotImplementedCommand() public { + deal(assetHubAgent, 50 ether); + Command command = Command.Reserved12; + + vm.expectEmit(true, false, false, false); + emit IOGateway.NotImplementedCommand(Command.Reserved12); + + vm.expectEmit(true, true, true, true); + emit IGatewayV1.InboundMessageDispatched(assetHubParaID.into(), 1, messageID, false); + + hoax(relayer, 1 ether); + vm.recordLogs(); + IGatewayV1(address(gateway)) + .submitV1( + InboundMessage( + assetHubParaID.into(), + 1, + command, + hex"", + maxDispatchGas, + maxRefund, + reward, + messageID + ), + proof, + makeMockProof() + ); + } +} diff --git a/contracts/test/snowbridge-data/test_vector_message_validator_1000.json b/contracts/test/snowbridge-data/test_vector_message_validator_1000.json new file mode 100644 index 000000000..c16dd6851 --- /dev/null +++ b/contracts/test/snowbridge-data/test_vector_message_validator_1000.json @@ -0,0 +1,1006 @@ +{ + "payload": "0x701500380000a10f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000010b000000000000000000000000000000000000000000000000000000000000010c000000000000000000000000000000000000000000000000000000000000010d000000000000000000000000000000000000000000000000000000000000010e000000000000000000000000000000000000000000000000000000000000010f0000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000000000000000001120000000000000000000000000000000000000000000000000000000000000113000000000000000000000000000000000000000000000000000000000000011400000000000000000000000000000000000000000000000000000000000001150000000000000000000000000000000000000000000000000000000000000116000000000000000000000000000000000000000000000000000000000000011700000000000000000000000000000000000000000000000000000000000001180000000000000000000000000000000000000000000000000000000000000119000000000000000000000000000000000000000000000000000000000000011a000000000000000000000000000000000000000000000000000000000000011b000000000000000000000000000000000000000000000000000000000000011c000000000000000000000000000000000000000000000000000000000000011d000000000000000000000000000000000000000000000000000000000000011e000000000000000000000000000000000000000000000000000000000000011f0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012100000000000000000000000000000000000000000000000000000000000001220000000000000000000000000000000000000000000000000000000000000123000000000000000000000000000000000000000000000000000000000000012400000000000000000000000000000000000000000000000000000000000001250000000000000000000000000000000000000000000000000000000000000126000000000000000000000000000000000000000000000000000000000000012700000000000000000000000000000000000000000000000000000000000001280000000000000000000000000000000000000000000000000000000000000129000000000000000000000000000000000000000000000000000000000000012a000000000000000000000000000000000000000000000000000000000000012b000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000012d000000000000000000000000000000000000000000000000000000000000012e000000000000000000000000000000000000000000000000000000000000012f0000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000001320000000000000000000000000000000000000000000000000000000000000133000000000000000000000000000000000000000000000000000000000000013400000000000000000000000000000000000000000000000000000000000001350000000000000000000000000000000000000000000000000000000000000136000000000000000000000000000000000000000000000000000000000000013700000000000000000000000000000000000000000000000000000000000001380000000000000000000000000000000000000000000000000000000000000139000000000000000000000000000000000000000000000000000000000000013a000000000000000000000000000000000000000000000000000000000000013b000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000013d000000000000000000000000000000000000000000000000000000000000013e000000000000000000000000000000000000000000000000000000000000013f0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f0000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e000000000000000000000000000000000000000000000000000000000000037f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be00000000000000000000000000000000000000000000000000000000000003bf00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e8ad27000000000000", + "accounts": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000014", + "0x0000000000000000000000000000000000000000000000000000000000000015", + "0x0000000000000000000000000000000000000000000000000000000000000016", + "0x0000000000000000000000000000000000000000000000000000000000000017", + "0x0000000000000000000000000000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000019", + "0x000000000000000000000000000000000000000000000000000000000000001a", + "0x000000000000000000000000000000000000000000000000000000000000001b", + "0x000000000000000000000000000000000000000000000000000000000000001c", + "0x000000000000000000000000000000000000000000000000000000000000001d", + "0x000000000000000000000000000000000000000000000000000000000000001e", + "0x000000000000000000000000000000000000000000000000000000000000001f", + "0x0000000000000000000000000000000000000000000000000000000000000020", + "0x0000000000000000000000000000000000000000000000000000000000000021", + "0x0000000000000000000000000000000000000000000000000000000000000022", + "0x0000000000000000000000000000000000000000000000000000000000000023", + "0x0000000000000000000000000000000000000000000000000000000000000024", + "0x0000000000000000000000000000000000000000000000000000000000000025", + "0x0000000000000000000000000000000000000000000000000000000000000026", + "0x0000000000000000000000000000000000000000000000000000000000000027", + "0x0000000000000000000000000000000000000000000000000000000000000028", + "0x0000000000000000000000000000000000000000000000000000000000000029", + "0x000000000000000000000000000000000000000000000000000000000000002a", + "0x000000000000000000000000000000000000000000000000000000000000002b", + "0x000000000000000000000000000000000000000000000000000000000000002c", + "0x000000000000000000000000000000000000000000000000000000000000002d", + "0x000000000000000000000000000000000000000000000000000000000000002e", + "0x000000000000000000000000000000000000000000000000000000000000002f", + "0x0000000000000000000000000000000000000000000000000000000000000030", + "0x0000000000000000000000000000000000000000000000000000000000000031", + "0x0000000000000000000000000000000000000000000000000000000000000032", + "0x0000000000000000000000000000000000000000000000000000000000000033", + "0x0000000000000000000000000000000000000000000000000000000000000034", + "0x0000000000000000000000000000000000000000000000000000000000000035", + "0x0000000000000000000000000000000000000000000000000000000000000036", + "0x0000000000000000000000000000000000000000000000000000000000000037", + "0x0000000000000000000000000000000000000000000000000000000000000038", + "0x0000000000000000000000000000000000000000000000000000000000000039", + "0x000000000000000000000000000000000000000000000000000000000000003a", + "0x000000000000000000000000000000000000000000000000000000000000003b", + "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x000000000000000000000000000000000000000000000000000000000000003d", + "0x000000000000000000000000000000000000000000000000000000000000003e", + "0x000000000000000000000000000000000000000000000000000000000000003f", + "0x0000000000000000000000000000000000000000000000000000000000000040", + "0x0000000000000000000000000000000000000000000000000000000000000041", + "0x0000000000000000000000000000000000000000000000000000000000000042", + "0x0000000000000000000000000000000000000000000000000000000000000043", + "0x0000000000000000000000000000000000000000000000000000000000000044", + "0x0000000000000000000000000000000000000000000000000000000000000045", + "0x0000000000000000000000000000000000000000000000000000000000000046", + "0x0000000000000000000000000000000000000000000000000000000000000047", + "0x0000000000000000000000000000000000000000000000000000000000000048", + "0x0000000000000000000000000000000000000000000000000000000000000049", + "0x000000000000000000000000000000000000000000000000000000000000004a", + "0x000000000000000000000000000000000000000000000000000000000000004b", + "0x000000000000000000000000000000000000000000000000000000000000004c", + "0x000000000000000000000000000000000000000000000000000000000000004d", + "0x000000000000000000000000000000000000000000000000000000000000004e", + "0x000000000000000000000000000000000000000000000000000000000000004f", + "0x0000000000000000000000000000000000000000000000000000000000000050", + "0x0000000000000000000000000000000000000000000000000000000000000051", + "0x0000000000000000000000000000000000000000000000000000000000000052", + "0x0000000000000000000000000000000000000000000000000000000000000053", + "0x0000000000000000000000000000000000000000000000000000000000000054", + "0x0000000000000000000000000000000000000000000000000000000000000055", + "0x0000000000000000000000000000000000000000000000000000000000000056", + "0x0000000000000000000000000000000000000000000000000000000000000057", + "0x0000000000000000000000000000000000000000000000000000000000000058", + "0x0000000000000000000000000000000000000000000000000000000000000059", + "0x000000000000000000000000000000000000000000000000000000000000005a", + "0x000000000000000000000000000000000000000000000000000000000000005b", + "0x000000000000000000000000000000000000000000000000000000000000005c", + "0x000000000000000000000000000000000000000000000000000000000000005d", + "0x000000000000000000000000000000000000000000000000000000000000005e", + "0x000000000000000000000000000000000000000000000000000000000000005f", + "0x0000000000000000000000000000000000000000000000000000000000000060", + "0x0000000000000000000000000000000000000000000000000000000000000061", + "0x0000000000000000000000000000000000000000000000000000000000000062", + "0x0000000000000000000000000000000000000000000000000000000000000063", + "0x0000000000000000000000000000000000000000000000000000000000000064", + "0x0000000000000000000000000000000000000000000000000000000000000065", + "0x0000000000000000000000000000000000000000000000000000000000000066", + "0x0000000000000000000000000000000000000000000000000000000000000067", + "0x0000000000000000000000000000000000000000000000000000000000000068", + "0x0000000000000000000000000000000000000000000000000000000000000069", + "0x000000000000000000000000000000000000000000000000000000000000006a", + "0x000000000000000000000000000000000000000000000000000000000000006b", + "0x000000000000000000000000000000000000000000000000000000000000006c", + "0x000000000000000000000000000000000000000000000000000000000000006d", + "0x000000000000000000000000000000000000000000000000000000000000006e", + "0x000000000000000000000000000000000000000000000000000000000000006f", + "0x0000000000000000000000000000000000000000000000000000000000000070", + "0x0000000000000000000000000000000000000000000000000000000000000071", + "0x0000000000000000000000000000000000000000000000000000000000000072", + "0x0000000000000000000000000000000000000000000000000000000000000073", + "0x0000000000000000000000000000000000000000000000000000000000000074", + "0x0000000000000000000000000000000000000000000000000000000000000075", + "0x0000000000000000000000000000000000000000000000000000000000000076", + "0x0000000000000000000000000000000000000000000000000000000000000077", + "0x0000000000000000000000000000000000000000000000000000000000000078", + "0x0000000000000000000000000000000000000000000000000000000000000079", + "0x000000000000000000000000000000000000000000000000000000000000007a", + "0x000000000000000000000000000000000000000000000000000000000000007b", + "0x000000000000000000000000000000000000000000000000000000000000007c", + "0x000000000000000000000000000000000000000000000000000000000000007d", + "0x000000000000000000000000000000000000000000000000000000000000007e", + "0x000000000000000000000000000000000000000000000000000000000000007f", + "0x0000000000000000000000000000000000000000000000000000000000000080", + "0x0000000000000000000000000000000000000000000000000000000000000081", + "0x0000000000000000000000000000000000000000000000000000000000000082", + "0x0000000000000000000000000000000000000000000000000000000000000083", + "0x0000000000000000000000000000000000000000000000000000000000000084", + "0x0000000000000000000000000000000000000000000000000000000000000085", + "0x0000000000000000000000000000000000000000000000000000000000000086", + "0x0000000000000000000000000000000000000000000000000000000000000087", + "0x0000000000000000000000000000000000000000000000000000000000000088", + "0x0000000000000000000000000000000000000000000000000000000000000089", + "0x000000000000000000000000000000000000000000000000000000000000008a", + "0x000000000000000000000000000000000000000000000000000000000000008b", + "0x000000000000000000000000000000000000000000000000000000000000008c", + "0x000000000000000000000000000000000000000000000000000000000000008d", + "0x000000000000000000000000000000000000000000000000000000000000008e", + "0x000000000000000000000000000000000000000000000000000000000000008f", + "0x0000000000000000000000000000000000000000000000000000000000000090", + "0x0000000000000000000000000000000000000000000000000000000000000091", + "0x0000000000000000000000000000000000000000000000000000000000000092", + "0x0000000000000000000000000000000000000000000000000000000000000093", + "0x0000000000000000000000000000000000000000000000000000000000000094", + "0x0000000000000000000000000000000000000000000000000000000000000095", + "0x0000000000000000000000000000000000000000000000000000000000000096", + "0x0000000000000000000000000000000000000000000000000000000000000097", + "0x0000000000000000000000000000000000000000000000000000000000000098", + "0x0000000000000000000000000000000000000000000000000000000000000099", + "0x000000000000000000000000000000000000000000000000000000000000009a", + "0x000000000000000000000000000000000000000000000000000000000000009b", + "0x000000000000000000000000000000000000000000000000000000000000009c", + "0x000000000000000000000000000000000000000000000000000000000000009d", + "0x000000000000000000000000000000000000000000000000000000000000009e", + "0x000000000000000000000000000000000000000000000000000000000000009f", + "0x00000000000000000000000000000000000000000000000000000000000000a0", + "0x00000000000000000000000000000000000000000000000000000000000000a1", + "0x00000000000000000000000000000000000000000000000000000000000000a2", + "0x00000000000000000000000000000000000000000000000000000000000000a3", + "0x00000000000000000000000000000000000000000000000000000000000000a4", + "0x00000000000000000000000000000000000000000000000000000000000000a5", + "0x00000000000000000000000000000000000000000000000000000000000000a6", + "0x00000000000000000000000000000000000000000000000000000000000000a7", + "0x00000000000000000000000000000000000000000000000000000000000000a8", + "0x00000000000000000000000000000000000000000000000000000000000000a9", + "0x00000000000000000000000000000000000000000000000000000000000000aa", + "0x00000000000000000000000000000000000000000000000000000000000000ab", + "0x00000000000000000000000000000000000000000000000000000000000000ac", + "0x00000000000000000000000000000000000000000000000000000000000000ad", + "0x00000000000000000000000000000000000000000000000000000000000000ae", + "0x00000000000000000000000000000000000000000000000000000000000000af", + "0x00000000000000000000000000000000000000000000000000000000000000b0", + "0x00000000000000000000000000000000000000000000000000000000000000b1", + "0x00000000000000000000000000000000000000000000000000000000000000b2", + "0x00000000000000000000000000000000000000000000000000000000000000b3", + "0x00000000000000000000000000000000000000000000000000000000000000b4", + "0x00000000000000000000000000000000000000000000000000000000000000b5", + "0x00000000000000000000000000000000000000000000000000000000000000b6", + "0x00000000000000000000000000000000000000000000000000000000000000b7", + "0x00000000000000000000000000000000000000000000000000000000000000b8", + "0x00000000000000000000000000000000000000000000000000000000000000b9", + "0x00000000000000000000000000000000000000000000000000000000000000ba", + "0x00000000000000000000000000000000000000000000000000000000000000bb", + "0x00000000000000000000000000000000000000000000000000000000000000bc", + "0x00000000000000000000000000000000000000000000000000000000000000bd", + "0x00000000000000000000000000000000000000000000000000000000000000be", + "0x00000000000000000000000000000000000000000000000000000000000000bf", + "0x00000000000000000000000000000000000000000000000000000000000000c0", + "0x00000000000000000000000000000000000000000000000000000000000000c1", + "0x00000000000000000000000000000000000000000000000000000000000000c2", + "0x00000000000000000000000000000000000000000000000000000000000000c3", + "0x00000000000000000000000000000000000000000000000000000000000000c4", + "0x00000000000000000000000000000000000000000000000000000000000000c5", + "0x00000000000000000000000000000000000000000000000000000000000000c6", + "0x00000000000000000000000000000000000000000000000000000000000000c7", + "0x00000000000000000000000000000000000000000000000000000000000000c8", + "0x00000000000000000000000000000000000000000000000000000000000000c9", + "0x00000000000000000000000000000000000000000000000000000000000000ca", + "0x00000000000000000000000000000000000000000000000000000000000000cb", + "0x00000000000000000000000000000000000000000000000000000000000000cc", + "0x00000000000000000000000000000000000000000000000000000000000000cd", + "0x00000000000000000000000000000000000000000000000000000000000000ce", + "0x00000000000000000000000000000000000000000000000000000000000000cf", + "0x00000000000000000000000000000000000000000000000000000000000000d0", + "0x00000000000000000000000000000000000000000000000000000000000000d1", + "0x00000000000000000000000000000000000000000000000000000000000000d2", + "0x00000000000000000000000000000000000000000000000000000000000000d3", + "0x00000000000000000000000000000000000000000000000000000000000000d4", + "0x00000000000000000000000000000000000000000000000000000000000000d5", + "0x00000000000000000000000000000000000000000000000000000000000000d6", + "0x00000000000000000000000000000000000000000000000000000000000000d7", + "0x00000000000000000000000000000000000000000000000000000000000000d8", + "0x00000000000000000000000000000000000000000000000000000000000000d9", + "0x00000000000000000000000000000000000000000000000000000000000000da", + "0x00000000000000000000000000000000000000000000000000000000000000db", + "0x00000000000000000000000000000000000000000000000000000000000000dc", + "0x00000000000000000000000000000000000000000000000000000000000000dd", + "0x00000000000000000000000000000000000000000000000000000000000000de", + "0x00000000000000000000000000000000000000000000000000000000000000df", + "0x00000000000000000000000000000000000000000000000000000000000000e0", + "0x00000000000000000000000000000000000000000000000000000000000000e1", + "0x00000000000000000000000000000000000000000000000000000000000000e2", + "0x00000000000000000000000000000000000000000000000000000000000000e3", + "0x00000000000000000000000000000000000000000000000000000000000000e4", + "0x00000000000000000000000000000000000000000000000000000000000000e5", + "0x00000000000000000000000000000000000000000000000000000000000000e6", + "0x00000000000000000000000000000000000000000000000000000000000000e7", + "0x00000000000000000000000000000000000000000000000000000000000000e8", + "0x00000000000000000000000000000000000000000000000000000000000000e9", + "0x00000000000000000000000000000000000000000000000000000000000000ea", + "0x00000000000000000000000000000000000000000000000000000000000000eb", + "0x00000000000000000000000000000000000000000000000000000000000000ec", + "0x00000000000000000000000000000000000000000000000000000000000000ed", + "0x00000000000000000000000000000000000000000000000000000000000000ee", + "0x00000000000000000000000000000000000000000000000000000000000000ef", + "0x00000000000000000000000000000000000000000000000000000000000000f0", + "0x00000000000000000000000000000000000000000000000000000000000000f1", + "0x00000000000000000000000000000000000000000000000000000000000000f2", + "0x00000000000000000000000000000000000000000000000000000000000000f3", + "0x00000000000000000000000000000000000000000000000000000000000000f4", + "0x00000000000000000000000000000000000000000000000000000000000000f5", + "0x00000000000000000000000000000000000000000000000000000000000000f6", + "0x00000000000000000000000000000000000000000000000000000000000000f7", + "0x00000000000000000000000000000000000000000000000000000000000000f8", + "0x00000000000000000000000000000000000000000000000000000000000000f9", + "0x00000000000000000000000000000000000000000000000000000000000000fa", + "0x00000000000000000000000000000000000000000000000000000000000000fb", + "0x00000000000000000000000000000000000000000000000000000000000000fc", + "0x00000000000000000000000000000000000000000000000000000000000000fd", + "0x00000000000000000000000000000000000000000000000000000000000000fe", + "0x00000000000000000000000000000000000000000000000000000000000000ff", + "0x0000000000000000000000000000000000000000000000000000000000000100", + "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000102", + "0x0000000000000000000000000000000000000000000000000000000000000103", + "0x0000000000000000000000000000000000000000000000000000000000000104", + "0x0000000000000000000000000000000000000000000000000000000000000105", + "0x0000000000000000000000000000000000000000000000000000000000000106", + "0x0000000000000000000000000000000000000000000000000000000000000107", + "0x0000000000000000000000000000000000000000000000000000000000000108", + "0x0000000000000000000000000000000000000000000000000000000000000109", + "0x000000000000000000000000000000000000000000000000000000000000010a", + "0x000000000000000000000000000000000000000000000000000000000000010b", + "0x000000000000000000000000000000000000000000000000000000000000010c", + "0x000000000000000000000000000000000000000000000000000000000000010d", + "0x000000000000000000000000000000000000000000000000000000000000010e", + "0x000000000000000000000000000000000000000000000000000000000000010f", + "0x0000000000000000000000000000000000000000000000000000000000000110", + "0x0000000000000000000000000000000000000000000000000000000000000111", + "0x0000000000000000000000000000000000000000000000000000000000000112", + "0x0000000000000000000000000000000000000000000000000000000000000113", + "0x0000000000000000000000000000000000000000000000000000000000000114", + "0x0000000000000000000000000000000000000000000000000000000000000115", + "0x0000000000000000000000000000000000000000000000000000000000000116", + "0x0000000000000000000000000000000000000000000000000000000000000117", + "0x0000000000000000000000000000000000000000000000000000000000000118", + "0x0000000000000000000000000000000000000000000000000000000000000119", + "0x000000000000000000000000000000000000000000000000000000000000011a", + "0x000000000000000000000000000000000000000000000000000000000000011b", + "0x000000000000000000000000000000000000000000000000000000000000011c", + "0x000000000000000000000000000000000000000000000000000000000000011d", + "0x000000000000000000000000000000000000000000000000000000000000011e", + "0x000000000000000000000000000000000000000000000000000000000000011f", + "0x0000000000000000000000000000000000000000000000000000000000000120", + "0x0000000000000000000000000000000000000000000000000000000000000121", + "0x0000000000000000000000000000000000000000000000000000000000000122", + "0x0000000000000000000000000000000000000000000000000000000000000123", + "0x0000000000000000000000000000000000000000000000000000000000000124", + "0x0000000000000000000000000000000000000000000000000000000000000125", + "0x0000000000000000000000000000000000000000000000000000000000000126", + "0x0000000000000000000000000000000000000000000000000000000000000127", + "0x0000000000000000000000000000000000000000000000000000000000000128", + "0x0000000000000000000000000000000000000000000000000000000000000129", + "0x000000000000000000000000000000000000000000000000000000000000012a", + "0x000000000000000000000000000000000000000000000000000000000000012b", + "0x000000000000000000000000000000000000000000000000000000000000012c", + "0x000000000000000000000000000000000000000000000000000000000000012d", + "0x000000000000000000000000000000000000000000000000000000000000012e", + "0x000000000000000000000000000000000000000000000000000000000000012f", + "0x0000000000000000000000000000000000000000000000000000000000000130", + "0x0000000000000000000000000000000000000000000000000000000000000131", + "0x0000000000000000000000000000000000000000000000000000000000000132", + "0x0000000000000000000000000000000000000000000000000000000000000133", + "0x0000000000000000000000000000000000000000000000000000000000000134", + "0x0000000000000000000000000000000000000000000000000000000000000135", + "0x0000000000000000000000000000000000000000000000000000000000000136", + "0x0000000000000000000000000000000000000000000000000000000000000137", + "0x0000000000000000000000000000000000000000000000000000000000000138", + "0x0000000000000000000000000000000000000000000000000000000000000139", + "0x000000000000000000000000000000000000000000000000000000000000013a", + "0x000000000000000000000000000000000000000000000000000000000000013b", + "0x000000000000000000000000000000000000000000000000000000000000013c", + "0x000000000000000000000000000000000000000000000000000000000000013d", + "0x000000000000000000000000000000000000000000000000000000000000013e", + "0x000000000000000000000000000000000000000000000000000000000000013f", + "0x0000000000000000000000000000000000000000000000000000000000000140", + "0x0000000000000000000000000000000000000000000000000000000000000141", + "0x0000000000000000000000000000000000000000000000000000000000000142", + "0x0000000000000000000000000000000000000000000000000000000000000143", + "0x0000000000000000000000000000000000000000000000000000000000000144", + "0x0000000000000000000000000000000000000000000000000000000000000145", + "0x0000000000000000000000000000000000000000000000000000000000000146", + "0x0000000000000000000000000000000000000000000000000000000000000147", + "0x0000000000000000000000000000000000000000000000000000000000000148", + "0x0000000000000000000000000000000000000000000000000000000000000149", + "0x000000000000000000000000000000000000000000000000000000000000014a", + "0x000000000000000000000000000000000000000000000000000000000000014b", + "0x000000000000000000000000000000000000000000000000000000000000014c", + "0x000000000000000000000000000000000000000000000000000000000000014d", + "0x000000000000000000000000000000000000000000000000000000000000014e", + "0x000000000000000000000000000000000000000000000000000000000000014f", + "0x0000000000000000000000000000000000000000000000000000000000000150", + "0x0000000000000000000000000000000000000000000000000000000000000151", + "0x0000000000000000000000000000000000000000000000000000000000000152", + "0x0000000000000000000000000000000000000000000000000000000000000153", + "0x0000000000000000000000000000000000000000000000000000000000000154", + "0x0000000000000000000000000000000000000000000000000000000000000155", + "0x0000000000000000000000000000000000000000000000000000000000000156", + "0x0000000000000000000000000000000000000000000000000000000000000157", + "0x0000000000000000000000000000000000000000000000000000000000000158", + "0x0000000000000000000000000000000000000000000000000000000000000159", + "0x000000000000000000000000000000000000000000000000000000000000015a", + "0x000000000000000000000000000000000000000000000000000000000000015b", + "0x000000000000000000000000000000000000000000000000000000000000015c", + "0x000000000000000000000000000000000000000000000000000000000000015d", + "0x000000000000000000000000000000000000000000000000000000000000015e", + "0x000000000000000000000000000000000000000000000000000000000000015f", + "0x0000000000000000000000000000000000000000000000000000000000000160", + "0x0000000000000000000000000000000000000000000000000000000000000161", + "0x0000000000000000000000000000000000000000000000000000000000000162", + "0x0000000000000000000000000000000000000000000000000000000000000163", + "0x0000000000000000000000000000000000000000000000000000000000000164", + "0x0000000000000000000000000000000000000000000000000000000000000165", + "0x0000000000000000000000000000000000000000000000000000000000000166", + "0x0000000000000000000000000000000000000000000000000000000000000167", + "0x0000000000000000000000000000000000000000000000000000000000000168", + "0x0000000000000000000000000000000000000000000000000000000000000169", + "0x000000000000000000000000000000000000000000000000000000000000016a", + "0x000000000000000000000000000000000000000000000000000000000000016b", + "0x000000000000000000000000000000000000000000000000000000000000016c", + "0x000000000000000000000000000000000000000000000000000000000000016d", + "0x000000000000000000000000000000000000000000000000000000000000016e", + "0x000000000000000000000000000000000000000000000000000000000000016f", + "0x0000000000000000000000000000000000000000000000000000000000000170", + "0x0000000000000000000000000000000000000000000000000000000000000171", + "0x0000000000000000000000000000000000000000000000000000000000000172", + "0x0000000000000000000000000000000000000000000000000000000000000173", + "0x0000000000000000000000000000000000000000000000000000000000000174", + "0x0000000000000000000000000000000000000000000000000000000000000175", + "0x0000000000000000000000000000000000000000000000000000000000000176", + "0x0000000000000000000000000000000000000000000000000000000000000177", + "0x0000000000000000000000000000000000000000000000000000000000000178", + "0x0000000000000000000000000000000000000000000000000000000000000179", + "0x000000000000000000000000000000000000000000000000000000000000017a", + "0x000000000000000000000000000000000000000000000000000000000000017b", + "0x000000000000000000000000000000000000000000000000000000000000017c", + "0x000000000000000000000000000000000000000000000000000000000000017d", + "0x000000000000000000000000000000000000000000000000000000000000017e", + "0x000000000000000000000000000000000000000000000000000000000000017f", + "0x0000000000000000000000000000000000000000000000000000000000000180", + "0x0000000000000000000000000000000000000000000000000000000000000181", + "0x0000000000000000000000000000000000000000000000000000000000000182", + "0x0000000000000000000000000000000000000000000000000000000000000183", + "0x0000000000000000000000000000000000000000000000000000000000000184", + "0x0000000000000000000000000000000000000000000000000000000000000185", + "0x0000000000000000000000000000000000000000000000000000000000000186", + "0x0000000000000000000000000000000000000000000000000000000000000187", + "0x0000000000000000000000000000000000000000000000000000000000000188", + "0x0000000000000000000000000000000000000000000000000000000000000189", + "0x000000000000000000000000000000000000000000000000000000000000018a", + "0x000000000000000000000000000000000000000000000000000000000000018b", + "0x000000000000000000000000000000000000000000000000000000000000018c", + "0x000000000000000000000000000000000000000000000000000000000000018d", + "0x000000000000000000000000000000000000000000000000000000000000018e", + "0x000000000000000000000000000000000000000000000000000000000000018f", + "0x0000000000000000000000000000000000000000000000000000000000000190", + "0x0000000000000000000000000000000000000000000000000000000000000191", + "0x0000000000000000000000000000000000000000000000000000000000000192", + "0x0000000000000000000000000000000000000000000000000000000000000193", + "0x0000000000000000000000000000000000000000000000000000000000000194", + "0x0000000000000000000000000000000000000000000000000000000000000195", + "0x0000000000000000000000000000000000000000000000000000000000000196", + "0x0000000000000000000000000000000000000000000000000000000000000197", + "0x0000000000000000000000000000000000000000000000000000000000000198", + "0x0000000000000000000000000000000000000000000000000000000000000199", + "0x000000000000000000000000000000000000000000000000000000000000019a", + "0x000000000000000000000000000000000000000000000000000000000000019b", + "0x000000000000000000000000000000000000000000000000000000000000019c", + "0x000000000000000000000000000000000000000000000000000000000000019d", + "0x000000000000000000000000000000000000000000000000000000000000019e", + "0x000000000000000000000000000000000000000000000000000000000000019f", + "0x00000000000000000000000000000000000000000000000000000000000001a0", + "0x00000000000000000000000000000000000000000000000000000000000001a1", + "0x00000000000000000000000000000000000000000000000000000000000001a2", + "0x00000000000000000000000000000000000000000000000000000000000001a3", + "0x00000000000000000000000000000000000000000000000000000000000001a4", + "0x00000000000000000000000000000000000000000000000000000000000001a5", + "0x00000000000000000000000000000000000000000000000000000000000001a6", + "0x00000000000000000000000000000000000000000000000000000000000001a7", + "0x00000000000000000000000000000000000000000000000000000000000001a8", + "0x00000000000000000000000000000000000000000000000000000000000001a9", + "0x00000000000000000000000000000000000000000000000000000000000001aa", + "0x00000000000000000000000000000000000000000000000000000000000001ab", + "0x00000000000000000000000000000000000000000000000000000000000001ac", + "0x00000000000000000000000000000000000000000000000000000000000001ad", + "0x00000000000000000000000000000000000000000000000000000000000001ae", + "0x00000000000000000000000000000000000000000000000000000000000001af", + "0x00000000000000000000000000000000000000000000000000000000000001b0", + "0x00000000000000000000000000000000000000000000000000000000000001b1", + "0x00000000000000000000000000000000000000000000000000000000000001b2", + "0x00000000000000000000000000000000000000000000000000000000000001b3", + "0x00000000000000000000000000000000000000000000000000000000000001b4", + "0x00000000000000000000000000000000000000000000000000000000000001b5", + "0x00000000000000000000000000000000000000000000000000000000000001b6", + "0x00000000000000000000000000000000000000000000000000000000000001b7", + "0x00000000000000000000000000000000000000000000000000000000000001b8", + "0x00000000000000000000000000000000000000000000000000000000000001b9", + "0x00000000000000000000000000000000000000000000000000000000000001ba", + "0x00000000000000000000000000000000000000000000000000000000000001bb", + "0x00000000000000000000000000000000000000000000000000000000000001bc", + "0x00000000000000000000000000000000000000000000000000000000000001bd", + "0x00000000000000000000000000000000000000000000000000000000000001be", + "0x00000000000000000000000000000000000000000000000000000000000001bf", + "0x00000000000000000000000000000000000000000000000000000000000001c0", + "0x00000000000000000000000000000000000000000000000000000000000001c1", + "0x00000000000000000000000000000000000000000000000000000000000001c2", + "0x00000000000000000000000000000000000000000000000000000000000001c3", + "0x00000000000000000000000000000000000000000000000000000000000001c4", + "0x00000000000000000000000000000000000000000000000000000000000001c5", + "0x00000000000000000000000000000000000000000000000000000000000001c6", + "0x00000000000000000000000000000000000000000000000000000000000001c7", + "0x00000000000000000000000000000000000000000000000000000000000001c8", + "0x00000000000000000000000000000000000000000000000000000000000001c9", + "0x00000000000000000000000000000000000000000000000000000000000001ca", + "0x00000000000000000000000000000000000000000000000000000000000001cb", + "0x00000000000000000000000000000000000000000000000000000000000001cc", + "0x00000000000000000000000000000000000000000000000000000000000001cd", + "0x00000000000000000000000000000000000000000000000000000000000001ce", + "0x00000000000000000000000000000000000000000000000000000000000001cf", + "0x00000000000000000000000000000000000000000000000000000000000001d0", + "0x00000000000000000000000000000000000000000000000000000000000001d1", + "0x00000000000000000000000000000000000000000000000000000000000001d2", + "0x00000000000000000000000000000000000000000000000000000000000001d3", + "0x00000000000000000000000000000000000000000000000000000000000001d4", + "0x00000000000000000000000000000000000000000000000000000000000001d5", + "0x00000000000000000000000000000000000000000000000000000000000001d6", + "0x00000000000000000000000000000000000000000000000000000000000001d7", + "0x00000000000000000000000000000000000000000000000000000000000001d8", + "0x00000000000000000000000000000000000000000000000000000000000001d9", + "0x00000000000000000000000000000000000000000000000000000000000001da", + "0x00000000000000000000000000000000000000000000000000000000000001db", + "0x00000000000000000000000000000000000000000000000000000000000001dc", + "0x00000000000000000000000000000000000000000000000000000000000001dd", + "0x00000000000000000000000000000000000000000000000000000000000001de", + "0x00000000000000000000000000000000000000000000000000000000000001df", + "0x00000000000000000000000000000000000000000000000000000000000001e0", + "0x00000000000000000000000000000000000000000000000000000000000001e1", + "0x00000000000000000000000000000000000000000000000000000000000001e2", + "0x00000000000000000000000000000000000000000000000000000000000001e3", + "0x00000000000000000000000000000000000000000000000000000000000001e4", + "0x00000000000000000000000000000000000000000000000000000000000001e5", + "0x00000000000000000000000000000000000000000000000000000000000001e6", + "0x00000000000000000000000000000000000000000000000000000000000001e7", + "0x00000000000000000000000000000000000000000000000000000000000001e8", + "0x00000000000000000000000000000000000000000000000000000000000001e9", + "0x00000000000000000000000000000000000000000000000000000000000001ea", + "0x00000000000000000000000000000000000000000000000000000000000001eb", + "0x00000000000000000000000000000000000000000000000000000000000001ec", + "0x00000000000000000000000000000000000000000000000000000000000001ed", + "0x00000000000000000000000000000000000000000000000000000000000001ee", + "0x00000000000000000000000000000000000000000000000000000000000001ef", + "0x00000000000000000000000000000000000000000000000000000000000001f0", + "0x00000000000000000000000000000000000000000000000000000000000001f1", + "0x00000000000000000000000000000000000000000000000000000000000001f2", + "0x00000000000000000000000000000000000000000000000000000000000001f3", + "0x00000000000000000000000000000000000000000000000000000000000001f4", + "0x00000000000000000000000000000000000000000000000000000000000001f5", + "0x00000000000000000000000000000000000000000000000000000000000001f6", + "0x00000000000000000000000000000000000000000000000000000000000001f7", + "0x00000000000000000000000000000000000000000000000000000000000001f8", + "0x00000000000000000000000000000000000000000000000000000000000001f9", + "0x00000000000000000000000000000000000000000000000000000000000001fa", + "0x00000000000000000000000000000000000000000000000000000000000001fb", + "0x00000000000000000000000000000000000000000000000000000000000001fc", + "0x00000000000000000000000000000000000000000000000000000000000001fd", + "0x00000000000000000000000000000000000000000000000000000000000001fe", + "0x00000000000000000000000000000000000000000000000000000000000001ff", + "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000201", + "0x0000000000000000000000000000000000000000000000000000000000000202", + "0x0000000000000000000000000000000000000000000000000000000000000203", + "0x0000000000000000000000000000000000000000000000000000000000000204", + "0x0000000000000000000000000000000000000000000000000000000000000205", + "0x0000000000000000000000000000000000000000000000000000000000000206", + "0x0000000000000000000000000000000000000000000000000000000000000207", + "0x0000000000000000000000000000000000000000000000000000000000000208", + "0x0000000000000000000000000000000000000000000000000000000000000209", + "0x000000000000000000000000000000000000000000000000000000000000020a", + "0x000000000000000000000000000000000000000000000000000000000000020b", + "0x000000000000000000000000000000000000000000000000000000000000020c", + "0x000000000000000000000000000000000000000000000000000000000000020d", + "0x000000000000000000000000000000000000000000000000000000000000020e", + "0x000000000000000000000000000000000000000000000000000000000000020f", + "0x0000000000000000000000000000000000000000000000000000000000000210", + "0x0000000000000000000000000000000000000000000000000000000000000211", + "0x0000000000000000000000000000000000000000000000000000000000000212", + "0x0000000000000000000000000000000000000000000000000000000000000213", + "0x0000000000000000000000000000000000000000000000000000000000000214", + "0x0000000000000000000000000000000000000000000000000000000000000215", + "0x0000000000000000000000000000000000000000000000000000000000000216", + "0x0000000000000000000000000000000000000000000000000000000000000217", + "0x0000000000000000000000000000000000000000000000000000000000000218", + "0x0000000000000000000000000000000000000000000000000000000000000219", + "0x000000000000000000000000000000000000000000000000000000000000021a", + "0x000000000000000000000000000000000000000000000000000000000000021b", + "0x000000000000000000000000000000000000000000000000000000000000021c", + "0x000000000000000000000000000000000000000000000000000000000000021d", + "0x000000000000000000000000000000000000000000000000000000000000021e", + "0x000000000000000000000000000000000000000000000000000000000000021f", + "0x0000000000000000000000000000000000000000000000000000000000000220", + "0x0000000000000000000000000000000000000000000000000000000000000221", + "0x0000000000000000000000000000000000000000000000000000000000000222", + "0x0000000000000000000000000000000000000000000000000000000000000223", + "0x0000000000000000000000000000000000000000000000000000000000000224", + "0x0000000000000000000000000000000000000000000000000000000000000225", + "0x0000000000000000000000000000000000000000000000000000000000000226", + "0x0000000000000000000000000000000000000000000000000000000000000227", + "0x0000000000000000000000000000000000000000000000000000000000000228", + "0x0000000000000000000000000000000000000000000000000000000000000229", + "0x000000000000000000000000000000000000000000000000000000000000022a", + "0x000000000000000000000000000000000000000000000000000000000000022b", + "0x000000000000000000000000000000000000000000000000000000000000022c", + "0x000000000000000000000000000000000000000000000000000000000000022d", + "0x000000000000000000000000000000000000000000000000000000000000022e", + "0x000000000000000000000000000000000000000000000000000000000000022f", + "0x0000000000000000000000000000000000000000000000000000000000000230", + "0x0000000000000000000000000000000000000000000000000000000000000231", + "0x0000000000000000000000000000000000000000000000000000000000000232", + "0x0000000000000000000000000000000000000000000000000000000000000233", + "0x0000000000000000000000000000000000000000000000000000000000000234", + "0x0000000000000000000000000000000000000000000000000000000000000235", + "0x0000000000000000000000000000000000000000000000000000000000000236", + "0x0000000000000000000000000000000000000000000000000000000000000237", + "0x0000000000000000000000000000000000000000000000000000000000000238", + "0x0000000000000000000000000000000000000000000000000000000000000239", + "0x000000000000000000000000000000000000000000000000000000000000023a", + "0x000000000000000000000000000000000000000000000000000000000000023b", + "0x000000000000000000000000000000000000000000000000000000000000023c", + "0x000000000000000000000000000000000000000000000000000000000000023d", + "0x000000000000000000000000000000000000000000000000000000000000023e", + "0x000000000000000000000000000000000000000000000000000000000000023f", + "0x0000000000000000000000000000000000000000000000000000000000000240", + "0x0000000000000000000000000000000000000000000000000000000000000241", + "0x0000000000000000000000000000000000000000000000000000000000000242", + "0x0000000000000000000000000000000000000000000000000000000000000243", + "0x0000000000000000000000000000000000000000000000000000000000000244", + "0x0000000000000000000000000000000000000000000000000000000000000245", + "0x0000000000000000000000000000000000000000000000000000000000000246", + "0x0000000000000000000000000000000000000000000000000000000000000247", + "0x0000000000000000000000000000000000000000000000000000000000000248", + "0x0000000000000000000000000000000000000000000000000000000000000249", + "0x000000000000000000000000000000000000000000000000000000000000024a", + "0x000000000000000000000000000000000000000000000000000000000000024b", + "0x000000000000000000000000000000000000000000000000000000000000024c", + "0x000000000000000000000000000000000000000000000000000000000000024d", + "0x000000000000000000000000000000000000000000000000000000000000024e", + "0x000000000000000000000000000000000000000000000000000000000000024f", + "0x0000000000000000000000000000000000000000000000000000000000000250", + "0x0000000000000000000000000000000000000000000000000000000000000251", + "0x0000000000000000000000000000000000000000000000000000000000000252", + "0x0000000000000000000000000000000000000000000000000000000000000253", + "0x0000000000000000000000000000000000000000000000000000000000000254", + "0x0000000000000000000000000000000000000000000000000000000000000255", + "0x0000000000000000000000000000000000000000000000000000000000000256", + "0x0000000000000000000000000000000000000000000000000000000000000257", + "0x0000000000000000000000000000000000000000000000000000000000000258", + "0x0000000000000000000000000000000000000000000000000000000000000259", + "0x000000000000000000000000000000000000000000000000000000000000025a", + "0x000000000000000000000000000000000000000000000000000000000000025b", + "0x000000000000000000000000000000000000000000000000000000000000025c", + "0x000000000000000000000000000000000000000000000000000000000000025d", + "0x000000000000000000000000000000000000000000000000000000000000025e", + "0x000000000000000000000000000000000000000000000000000000000000025f", + "0x0000000000000000000000000000000000000000000000000000000000000260", + "0x0000000000000000000000000000000000000000000000000000000000000261", + "0x0000000000000000000000000000000000000000000000000000000000000262", + "0x0000000000000000000000000000000000000000000000000000000000000263", + "0x0000000000000000000000000000000000000000000000000000000000000264", + "0x0000000000000000000000000000000000000000000000000000000000000265", + "0x0000000000000000000000000000000000000000000000000000000000000266", + "0x0000000000000000000000000000000000000000000000000000000000000267", + "0x0000000000000000000000000000000000000000000000000000000000000268", + "0x0000000000000000000000000000000000000000000000000000000000000269", + "0x000000000000000000000000000000000000000000000000000000000000026a", + "0x000000000000000000000000000000000000000000000000000000000000026b", + "0x000000000000000000000000000000000000000000000000000000000000026c", + "0x000000000000000000000000000000000000000000000000000000000000026d", + "0x000000000000000000000000000000000000000000000000000000000000026e", + "0x000000000000000000000000000000000000000000000000000000000000026f", + "0x0000000000000000000000000000000000000000000000000000000000000270", + "0x0000000000000000000000000000000000000000000000000000000000000271", + "0x0000000000000000000000000000000000000000000000000000000000000272", + "0x0000000000000000000000000000000000000000000000000000000000000273", + "0x0000000000000000000000000000000000000000000000000000000000000274", + "0x0000000000000000000000000000000000000000000000000000000000000275", + "0x0000000000000000000000000000000000000000000000000000000000000276", + "0x0000000000000000000000000000000000000000000000000000000000000277", + "0x0000000000000000000000000000000000000000000000000000000000000278", + "0x0000000000000000000000000000000000000000000000000000000000000279", + "0x000000000000000000000000000000000000000000000000000000000000027a", + "0x000000000000000000000000000000000000000000000000000000000000027b", + "0x000000000000000000000000000000000000000000000000000000000000027c", + "0x000000000000000000000000000000000000000000000000000000000000027d", + "0x000000000000000000000000000000000000000000000000000000000000027e", + "0x000000000000000000000000000000000000000000000000000000000000027f", + "0x0000000000000000000000000000000000000000000000000000000000000280", + "0x0000000000000000000000000000000000000000000000000000000000000281", + "0x0000000000000000000000000000000000000000000000000000000000000282", + "0x0000000000000000000000000000000000000000000000000000000000000283", + "0x0000000000000000000000000000000000000000000000000000000000000284", + "0x0000000000000000000000000000000000000000000000000000000000000285", + "0x0000000000000000000000000000000000000000000000000000000000000286", + "0x0000000000000000000000000000000000000000000000000000000000000287", + "0x0000000000000000000000000000000000000000000000000000000000000288", + "0x0000000000000000000000000000000000000000000000000000000000000289", + "0x000000000000000000000000000000000000000000000000000000000000028a", + "0x000000000000000000000000000000000000000000000000000000000000028b", + "0x000000000000000000000000000000000000000000000000000000000000028c", + "0x000000000000000000000000000000000000000000000000000000000000028d", + "0x000000000000000000000000000000000000000000000000000000000000028e", + "0x000000000000000000000000000000000000000000000000000000000000028f", + "0x0000000000000000000000000000000000000000000000000000000000000290", + "0x0000000000000000000000000000000000000000000000000000000000000291", + "0x0000000000000000000000000000000000000000000000000000000000000292", + "0x0000000000000000000000000000000000000000000000000000000000000293", + "0x0000000000000000000000000000000000000000000000000000000000000294", + "0x0000000000000000000000000000000000000000000000000000000000000295", + "0x0000000000000000000000000000000000000000000000000000000000000296", + "0x0000000000000000000000000000000000000000000000000000000000000297", + "0x0000000000000000000000000000000000000000000000000000000000000298", + "0x0000000000000000000000000000000000000000000000000000000000000299", + "0x000000000000000000000000000000000000000000000000000000000000029a", + "0x000000000000000000000000000000000000000000000000000000000000029b", + "0x000000000000000000000000000000000000000000000000000000000000029c", + "0x000000000000000000000000000000000000000000000000000000000000029d", + "0x000000000000000000000000000000000000000000000000000000000000029e", + "0x000000000000000000000000000000000000000000000000000000000000029f", + "0x00000000000000000000000000000000000000000000000000000000000002a0", + "0x00000000000000000000000000000000000000000000000000000000000002a1", + "0x00000000000000000000000000000000000000000000000000000000000002a2", + "0x00000000000000000000000000000000000000000000000000000000000002a3", + "0x00000000000000000000000000000000000000000000000000000000000002a4", + "0x00000000000000000000000000000000000000000000000000000000000002a5", + "0x00000000000000000000000000000000000000000000000000000000000002a6", + "0x00000000000000000000000000000000000000000000000000000000000002a7", + "0x00000000000000000000000000000000000000000000000000000000000002a8", + "0x00000000000000000000000000000000000000000000000000000000000002a9", + "0x00000000000000000000000000000000000000000000000000000000000002aa", + "0x00000000000000000000000000000000000000000000000000000000000002ab", + "0x00000000000000000000000000000000000000000000000000000000000002ac", + "0x00000000000000000000000000000000000000000000000000000000000002ad", + "0x00000000000000000000000000000000000000000000000000000000000002ae", + "0x00000000000000000000000000000000000000000000000000000000000002af", + "0x00000000000000000000000000000000000000000000000000000000000002b0", + "0x00000000000000000000000000000000000000000000000000000000000002b1", + "0x00000000000000000000000000000000000000000000000000000000000002b2", + "0x00000000000000000000000000000000000000000000000000000000000002b3", + "0x00000000000000000000000000000000000000000000000000000000000002b4", + "0x00000000000000000000000000000000000000000000000000000000000002b5", + "0x00000000000000000000000000000000000000000000000000000000000002b6", + "0x00000000000000000000000000000000000000000000000000000000000002b7", + "0x00000000000000000000000000000000000000000000000000000000000002b8", + "0x00000000000000000000000000000000000000000000000000000000000002b9", + "0x00000000000000000000000000000000000000000000000000000000000002ba", + "0x00000000000000000000000000000000000000000000000000000000000002bb", + "0x00000000000000000000000000000000000000000000000000000000000002bc", + "0x00000000000000000000000000000000000000000000000000000000000002bd", + "0x00000000000000000000000000000000000000000000000000000000000002be", + "0x00000000000000000000000000000000000000000000000000000000000002bf", + "0x00000000000000000000000000000000000000000000000000000000000002c0", + "0x00000000000000000000000000000000000000000000000000000000000002c1", + "0x00000000000000000000000000000000000000000000000000000000000002c2", + "0x00000000000000000000000000000000000000000000000000000000000002c3", + "0x00000000000000000000000000000000000000000000000000000000000002c4", + "0x00000000000000000000000000000000000000000000000000000000000002c5", + "0x00000000000000000000000000000000000000000000000000000000000002c6", + "0x00000000000000000000000000000000000000000000000000000000000002c7", + "0x00000000000000000000000000000000000000000000000000000000000002c8", + "0x00000000000000000000000000000000000000000000000000000000000002c9", + "0x00000000000000000000000000000000000000000000000000000000000002ca", + "0x00000000000000000000000000000000000000000000000000000000000002cb", + "0x00000000000000000000000000000000000000000000000000000000000002cc", + "0x00000000000000000000000000000000000000000000000000000000000002cd", + "0x00000000000000000000000000000000000000000000000000000000000002ce", + "0x00000000000000000000000000000000000000000000000000000000000002cf", + "0x00000000000000000000000000000000000000000000000000000000000002d0", + "0x00000000000000000000000000000000000000000000000000000000000002d1", + "0x00000000000000000000000000000000000000000000000000000000000002d2", + "0x00000000000000000000000000000000000000000000000000000000000002d3", + "0x00000000000000000000000000000000000000000000000000000000000002d4", + "0x00000000000000000000000000000000000000000000000000000000000002d5", + "0x00000000000000000000000000000000000000000000000000000000000002d6", + "0x00000000000000000000000000000000000000000000000000000000000002d7", + "0x00000000000000000000000000000000000000000000000000000000000002d8", + "0x00000000000000000000000000000000000000000000000000000000000002d9", + "0x00000000000000000000000000000000000000000000000000000000000002da", + "0x00000000000000000000000000000000000000000000000000000000000002db", + "0x00000000000000000000000000000000000000000000000000000000000002dc", + "0x00000000000000000000000000000000000000000000000000000000000002dd", + "0x00000000000000000000000000000000000000000000000000000000000002de", + "0x00000000000000000000000000000000000000000000000000000000000002df", + "0x00000000000000000000000000000000000000000000000000000000000002e0", + "0x00000000000000000000000000000000000000000000000000000000000002e1", + "0x00000000000000000000000000000000000000000000000000000000000002e2", + "0x00000000000000000000000000000000000000000000000000000000000002e3", + "0x00000000000000000000000000000000000000000000000000000000000002e4", + "0x00000000000000000000000000000000000000000000000000000000000002e5", + "0x00000000000000000000000000000000000000000000000000000000000002e6", + "0x00000000000000000000000000000000000000000000000000000000000002e7", + "0x00000000000000000000000000000000000000000000000000000000000002e8", + "0x00000000000000000000000000000000000000000000000000000000000002e9", + "0x00000000000000000000000000000000000000000000000000000000000002ea", + "0x00000000000000000000000000000000000000000000000000000000000002eb", + "0x00000000000000000000000000000000000000000000000000000000000002ec", + "0x00000000000000000000000000000000000000000000000000000000000002ed", + "0x00000000000000000000000000000000000000000000000000000000000002ee", + "0x00000000000000000000000000000000000000000000000000000000000002ef", + "0x00000000000000000000000000000000000000000000000000000000000002f0", + "0x00000000000000000000000000000000000000000000000000000000000002f1", + "0x00000000000000000000000000000000000000000000000000000000000002f2", + "0x00000000000000000000000000000000000000000000000000000000000002f3", + "0x00000000000000000000000000000000000000000000000000000000000002f4", + "0x00000000000000000000000000000000000000000000000000000000000002f5", + "0x00000000000000000000000000000000000000000000000000000000000002f6", + "0x00000000000000000000000000000000000000000000000000000000000002f7", + "0x00000000000000000000000000000000000000000000000000000000000002f8", + "0x00000000000000000000000000000000000000000000000000000000000002f9", + "0x00000000000000000000000000000000000000000000000000000000000002fa", + "0x00000000000000000000000000000000000000000000000000000000000002fb", + "0x00000000000000000000000000000000000000000000000000000000000002fc", + "0x00000000000000000000000000000000000000000000000000000000000002fd", + "0x00000000000000000000000000000000000000000000000000000000000002fe", + "0x00000000000000000000000000000000000000000000000000000000000002ff", + "0x0000000000000000000000000000000000000000000000000000000000000300", + "0x0000000000000000000000000000000000000000000000000000000000000301", + "0x0000000000000000000000000000000000000000000000000000000000000302", + "0x0000000000000000000000000000000000000000000000000000000000000303", + "0x0000000000000000000000000000000000000000000000000000000000000304", + "0x0000000000000000000000000000000000000000000000000000000000000305", + "0x0000000000000000000000000000000000000000000000000000000000000306", + "0x0000000000000000000000000000000000000000000000000000000000000307", + "0x0000000000000000000000000000000000000000000000000000000000000308", + "0x0000000000000000000000000000000000000000000000000000000000000309", + "0x000000000000000000000000000000000000000000000000000000000000030a", + "0x000000000000000000000000000000000000000000000000000000000000030b", + "0x000000000000000000000000000000000000000000000000000000000000030c", + "0x000000000000000000000000000000000000000000000000000000000000030d", + "0x000000000000000000000000000000000000000000000000000000000000030e", + "0x000000000000000000000000000000000000000000000000000000000000030f", + "0x0000000000000000000000000000000000000000000000000000000000000310", + "0x0000000000000000000000000000000000000000000000000000000000000311", + "0x0000000000000000000000000000000000000000000000000000000000000312", + "0x0000000000000000000000000000000000000000000000000000000000000313", + "0x0000000000000000000000000000000000000000000000000000000000000314", + "0x0000000000000000000000000000000000000000000000000000000000000315", + "0x0000000000000000000000000000000000000000000000000000000000000316", + "0x0000000000000000000000000000000000000000000000000000000000000317", + "0x0000000000000000000000000000000000000000000000000000000000000318", + "0x0000000000000000000000000000000000000000000000000000000000000319", + "0x000000000000000000000000000000000000000000000000000000000000031a", + "0x000000000000000000000000000000000000000000000000000000000000031b", + "0x000000000000000000000000000000000000000000000000000000000000031c", + "0x000000000000000000000000000000000000000000000000000000000000031d", + "0x000000000000000000000000000000000000000000000000000000000000031e", + "0x000000000000000000000000000000000000000000000000000000000000031f", + "0x0000000000000000000000000000000000000000000000000000000000000320", + "0x0000000000000000000000000000000000000000000000000000000000000321", + "0x0000000000000000000000000000000000000000000000000000000000000322", + "0x0000000000000000000000000000000000000000000000000000000000000323", + "0x0000000000000000000000000000000000000000000000000000000000000324", + "0x0000000000000000000000000000000000000000000000000000000000000325", + "0x0000000000000000000000000000000000000000000000000000000000000326", + "0x0000000000000000000000000000000000000000000000000000000000000327", + "0x0000000000000000000000000000000000000000000000000000000000000328", + "0x0000000000000000000000000000000000000000000000000000000000000329", + "0x000000000000000000000000000000000000000000000000000000000000032a", + "0x000000000000000000000000000000000000000000000000000000000000032b", + "0x000000000000000000000000000000000000000000000000000000000000032c", + "0x000000000000000000000000000000000000000000000000000000000000032d", + "0x000000000000000000000000000000000000000000000000000000000000032e", + "0x000000000000000000000000000000000000000000000000000000000000032f", + "0x0000000000000000000000000000000000000000000000000000000000000330", + "0x0000000000000000000000000000000000000000000000000000000000000331", + "0x0000000000000000000000000000000000000000000000000000000000000332", + "0x0000000000000000000000000000000000000000000000000000000000000333", + "0x0000000000000000000000000000000000000000000000000000000000000334", + "0x0000000000000000000000000000000000000000000000000000000000000335", + "0x0000000000000000000000000000000000000000000000000000000000000336", + "0x0000000000000000000000000000000000000000000000000000000000000337", + "0x0000000000000000000000000000000000000000000000000000000000000338", + "0x0000000000000000000000000000000000000000000000000000000000000339", + "0x000000000000000000000000000000000000000000000000000000000000033a", + "0x000000000000000000000000000000000000000000000000000000000000033b", + "0x000000000000000000000000000000000000000000000000000000000000033c", + "0x000000000000000000000000000000000000000000000000000000000000033d", + "0x000000000000000000000000000000000000000000000000000000000000033e", + "0x000000000000000000000000000000000000000000000000000000000000033f", + "0x0000000000000000000000000000000000000000000000000000000000000340", + "0x0000000000000000000000000000000000000000000000000000000000000341", + "0x0000000000000000000000000000000000000000000000000000000000000342", + "0x0000000000000000000000000000000000000000000000000000000000000343", + "0x0000000000000000000000000000000000000000000000000000000000000344", + "0x0000000000000000000000000000000000000000000000000000000000000345", + "0x0000000000000000000000000000000000000000000000000000000000000346", + "0x0000000000000000000000000000000000000000000000000000000000000347", + "0x0000000000000000000000000000000000000000000000000000000000000348", + "0x0000000000000000000000000000000000000000000000000000000000000349", + "0x000000000000000000000000000000000000000000000000000000000000034a", + "0x000000000000000000000000000000000000000000000000000000000000034b", + "0x000000000000000000000000000000000000000000000000000000000000034c", + "0x000000000000000000000000000000000000000000000000000000000000034d", + "0x000000000000000000000000000000000000000000000000000000000000034e", + "0x000000000000000000000000000000000000000000000000000000000000034f", + "0x0000000000000000000000000000000000000000000000000000000000000350", + "0x0000000000000000000000000000000000000000000000000000000000000351", + "0x0000000000000000000000000000000000000000000000000000000000000352", + "0x0000000000000000000000000000000000000000000000000000000000000353", + "0x0000000000000000000000000000000000000000000000000000000000000354", + "0x0000000000000000000000000000000000000000000000000000000000000355", + "0x0000000000000000000000000000000000000000000000000000000000000356", + "0x0000000000000000000000000000000000000000000000000000000000000357", + "0x0000000000000000000000000000000000000000000000000000000000000358", + "0x0000000000000000000000000000000000000000000000000000000000000359", + "0x000000000000000000000000000000000000000000000000000000000000035a", + "0x000000000000000000000000000000000000000000000000000000000000035b", + "0x000000000000000000000000000000000000000000000000000000000000035c", + "0x000000000000000000000000000000000000000000000000000000000000035d", + "0x000000000000000000000000000000000000000000000000000000000000035e", + "0x000000000000000000000000000000000000000000000000000000000000035f", + "0x0000000000000000000000000000000000000000000000000000000000000360", + "0x0000000000000000000000000000000000000000000000000000000000000361", + "0x0000000000000000000000000000000000000000000000000000000000000362", + "0x0000000000000000000000000000000000000000000000000000000000000363", + "0x0000000000000000000000000000000000000000000000000000000000000364", + "0x0000000000000000000000000000000000000000000000000000000000000365", + "0x0000000000000000000000000000000000000000000000000000000000000366", + "0x0000000000000000000000000000000000000000000000000000000000000367", + "0x0000000000000000000000000000000000000000000000000000000000000368", + "0x0000000000000000000000000000000000000000000000000000000000000369", + "0x000000000000000000000000000000000000000000000000000000000000036a", + "0x000000000000000000000000000000000000000000000000000000000000036b", + "0x000000000000000000000000000000000000000000000000000000000000036c", + "0x000000000000000000000000000000000000000000000000000000000000036d", + "0x000000000000000000000000000000000000000000000000000000000000036e", + "0x000000000000000000000000000000000000000000000000000000000000036f", + "0x0000000000000000000000000000000000000000000000000000000000000370", + "0x0000000000000000000000000000000000000000000000000000000000000371", + "0x0000000000000000000000000000000000000000000000000000000000000372", + "0x0000000000000000000000000000000000000000000000000000000000000373", + "0x0000000000000000000000000000000000000000000000000000000000000374", + "0x0000000000000000000000000000000000000000000000000000000000000375", + "0x0000000000000000000000000000000000000000000000000000000000000376", + "0x0000000000000000000000000000000000000000000000000000000000000377", + "0x0000000000000000000000000000000000000000000000000000000000000378", + "0x0000000000000000000000000000000000000000000000000000000000000379", + "0x000000000000000000000000000000000000000000000000000000000000037a", + "0x000000000000000000000000000000000000000000000000000000000000037b", + "0x000000000000000000000000000000000000000000000000000000000000037c", + "0x000000000000000000000000000000000000000000000000000000000000037d", + "0x000000000000000000000000000000000000000000000000000000000000037e", + "0x000000000000000000000000000000000000000000000000000000000000037f", + "0x0000000000000000000000000000000000000000000000000000000000000380", + "0x0000000000000000000000000000000000000000000000000000000000000381", + "0x0000000000000000000000000000000000000000000000000000000000000382", + "0x0000000000000000000000000000000000000000000000000000000000000383", + "0x0000000000000000000000000000000000000000000000000000000000000384", + "0x0000000000000000000000000000000000000000000000000000000000000385", + "0x0000000000000000000000000000000000000000000000000000000000000386", + "0x0000000000000000000000000000000000000000000000000000000000000387", + "0x0000000000000000000000000000000000000000000000000000000000000388", + "0x0000000000000000000000000000000000000000000000000000000000000389", + "0x000000000000000000000000000000000000000000000000000000000000038a", + "0x000000000000000000000000000000000000000000000000000000000000038b", + "0x000000000000000000000000000000000000000000000000000000000000038c", + "0x000000000000000000000000000000000000000000000000000000000000038d", + "0x000000000000000000000000000000000000000000000000000000000000038e", + "0x000000000000000000000000000000000000000000000000000000000000038f", + "0x0000000000000000000000000000000000000000000000000000000000000390", + "0x0000000000000000000000000000000000000000000000000000000000000391", + "0x0000000000000000000000000000000000000000000000000000000000000392", + "0x0000000000000000000000000000000000000000000000000000000000000393", + "0x0000000000000000000000000000000000000000000000000000000000000394", + "0x0000000000000000000000000000000000000000000000000000000000000395", + "0x0000000000000000000000000000000000000000000000000000000000000396", + "0x0000000000000000000000000000000000000000000000000000000000000397", + "0x0000000000000000000000000000000000000000000000000000000000000398", + "0x0000000000000000000000000000000000000000000000000000000000000399", + "0x000000000000000000000000000000000000000000000000000000000000039a", + "0x000000000000000000000000000000000000000000000000000000000000039b", + "0x000000000000000000000000000000000000000000000000000000000000039c", + "0x000000000000000000000000000000000000000000000000000000000000039d", + "0x000000000000000000000000000000000000000000000000000000000000039e", + "0x000000000000000000000000000000000000000000000000000000000000039f", + "0x00000000000000000000000000000000000000000000000000000000000003a0", + "0x00000000000000000000000000000000000000000000000000000000000003a1", + "0x00000000000000000000000000000000000000000000000000000000000003a2", + "0x00000000000000000000000000000000000000000000000000000000000003a3", + "0x00000000000000000000000000000000000000000000000000000000000003a4", + "0x00000000000000000000000000000000000000000000000000000000000003a5", + "0x00000000000000000000000000000000000000000000000000000000000003a6", + "0x00000000000000000000000000000000000000000000000000000000000003a7", + "0x00000000000000000000000000000000000000000000000000000000000003a8", + "0x00000000000000000000000000000000000000000000000000000000000003a9", + "0x00000000000000000000000000000000000000000000000000000000000003aa", + "0x00000000000000000000000000000000000000000000000000000000000003ab", + "0x00000000000000000000000000000000000000000000000000000000000003ac", + "0x00000000000000000000000000000000000000000000000000000000000003ad", + "0x00000000000000000000000000000000000000000000000000000000000003ae", + "0x00000000000000000000000000000000000000000000000000000000000003af", + "0x00000000000000000000000000000000000000000000000000000000000003b0", + "0x00000000000000000000000000000000000000000000000000000000000003b1", + "0x00000000000000000000000000000000000000000000000000000000000003b2", + "0x00000000000000000000000000000000000000000000000000000000000003b3", + "0x00000000000000000000000000000000000000000000000000000000000003b4", + "0x00000000000000000000000000000000000000000000000000000000000003b5", + "0x00000000000000000000000000000000000000000000000000000000000003b6", + "0x00000000000000000000000000000000000000000000000000000000000003b7", + "0x00000000000000000000000000000000000000000000000000000000000003b8", + "0x00000000000000000000000000000000000000000000000000000000000003b9", + "0x00000000000000000000000000000000000000000000000000000000000003ba", + "0x00000000000000000000000000000000000000000000000000000000000003bb", + "0x00000000000000000000000000000000000000000000000000000000000003bc", + "0x00000000000000000000000000000000000000000000000000000000000003bd", + "0x00000000000000000000000000000000000000000000000000000000000003be", + "0x00000000000000000000000000000000000000000000000000000000000003bf", + "0x00000000000000000000000000000000000000000000000000000000000003c0", + "0x00000000000000000000000000000000000000000000000000000000000003c1", + "0x00000000000000000000000000000000000000000000000000000000000003c2", + "0x00000000000000000000000000000000000000000000000000000000000003c3", + "0x00000000000000000000000000000000000000000000000000000000000003c4", + "0x00000000000000000000000000000000000000000000000000000000000003c5", + "0x00000000000000000000000000000000000000000000000000000000000003c6", + "0x00000000000000000000000000000000000000000000000000000000000003c7", + "0x00000000000000000000000000000000000000000000000000000000000003c8", + "0x00000000000000000000000000000000000000000000000000000000000003c9", + "0x00000000000000000000000000000000000000000000000000000000000003ca", + "0x00000000000000000000000000000000000000000000000000000000000003cb", + "0x00000000000000000000000000000000000000000000000000000000000003cc", + "0x00000000000000000000000000000000000000000000000000000000000003cd", + "0x00000000000000000000000000000000000000000000000000000000000003ce", + "0x00000000000000000000000000000000000000000000000000000000000003cf", + "0x00000000000000000000000000000000000000000000000000000000000003d0", + "0x00000000000000000000000000000000000000000000000000000000000003d1", + "0x00000000000000000000000000000000000000000000000000000000000003d2", + "0x00000000000000000000000000000000000000000000000000000000000003d3", + "0x00000000000000000000000000000000000000000000000000000000000003d4", + "0x00000000000000000000000000000000000000000000000000000000000003d5", + "0x00000000000000000000000000000000000000000000000000000000000003d6", + "0x00000000000000000000000000000000000000000000000000000000000003d7", + "0x00000000000000000000000000000000000000000000000000000000000003d8", + "0x00000000000000000000000000000000000000000000000000000000000003d9", + "0x00000000000000000000000000000000000000000000000000000000000003da", + "0x00000000000000000000000000000000000000000000000000000000000003db", + "0x00000000000000000000000000000000000000000000000000000000000003dc", + "0x00000000000000000000000000000000000000000000000000000000000003dd", + "0x00000000000000000000000000000000000000000000000000000000000003de", + "0x00000000000000000000000000000000000000000000000000000000000003df", + "0x00000000000000000000000000000000000000000000000000000000000003e0", + "0x00000000000000000000000000000000000000000000000000000000000003e1", + "0x00000000000000000000000000000000000000000000000000000000000003e2", + "0x00000000000000000000000000000000000000000000000000000000000003e3", + "0x00000000000000000000000000000000000000000000000000000000000003e4", + "0x00000000000000000000000000000000000000000000000000000000000003e5", + "0x00000000000000000000000000000000000000000000000000000000000003e6", + "0x00000000000000000000000000000000000000000000000000000000000003e7", + "0x00000000000000000000000000000000000000000000000000000000000003e8" + ], + "epoch": 10157 +} diff --git a/contracts/test/snowbridge-data/test_vector_message_validator_400.json b/contracts/test/snowbridge-data/test_vector_message_validator_400.json new file mode 100644 index 000000000..77eb391df --- /dev/null +++ b/contracts/test/snowbridge-data/test_vector_message_validator_400.json @@ -0,0 +1,406 @@ +{ + "payload": "0x7015003800004106000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004100000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000043000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004700000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000049000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000004b000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004d000000000000000000000000000000000000000000000000000000000000004e000000000000000000000000000000000000000000000000000000000000004f0000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005100000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000053000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005700000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000059000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005f0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006100000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000063000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000006700000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000069000000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006f0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007100000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000073000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000750000000000000000000000000000000000000000000000000000000000000076000000000000000000000000000000000000000000000000000000000000007700000000000000000000000000000000000000000000000000000000000000780000000000000000000000000000000000000000000000000000000000000079000000000000000000000000000000000000000000000000000000000000007a000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000007e000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000083000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000850000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000880000000000000000000000000000000000000000000000000000000000000089000000000000000000000000000000000000000000000000000000000000008a000000000000000000000000000000000000000000000000000000000000008b000000000000000000000000000000000000000000000000000000000000008c000000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000000008e000000000000000000000000000000000000000000000000000000000000008f0000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000009100000000000000000000000000000000000000000000000000000000000000920000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000000000000000000000000000950000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000009700000000000000000000000000000000000000000000000000000000000000980000000000000000000000000000000000000000000000000000000000000099000000000000000000000000000000000000000000000000000000000000009a000000000000000000000000000000000000000000000000000000000000009b000000000000000000000000000000000000000000000000000000000000009c000000000000000000000000000000000000000000000000000000000000009d000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000009f00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a100000000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000000000000000a300000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000a500000000000000000000000000000000000000000000000000000000000000a600000000000000000000000000000000000000000000000000000000000000a700000000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000000000000000a900000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000ab00000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000ad00000000000000000000000000000000000000000000000000000000000000ae00000000000000000000000000000000000000000000000000000000000000af00000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000b100000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000b300000000000000000000000000000000000000000000000000000000000000b400000000000000000000000000000000000000000000000000000000000000b500000000000000000000000000000000000000000000000000000000000000b600000000000000000000000000000000000000000000000000000000000000b700000000000000000000000000000000000000000000000000000000000000b800000000000000000000000000000000000000000000000000000000000000b900000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000bb00000000000000000000000000000000000000000000000000000000000000bc00000000000000000000000000000000000000000000000000000000000000bd00000000000000000000000000000000000000000000000000000000000000be00000000000000000000000000000000000000000000000000000000000000bf00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c300000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c500000000000000000000000000000000000000000000000000000000000000c600000000000000000000000000000000000000000000000000000000000000c700000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c900000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000cb00000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000cd00000000000000000000000000000000000000000000000000000000000000ce00000000000000000000000000000000000000000000000000000000000000cf00000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000d100000000000000000000000000000000000000000000000000000000000000d200000000000000000000000000000000000000000000000000000000000000d300000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000d500000000000000000000000000000000000000000000000000000000000000d600000000000000000000000000000000000000000000000000000000000000d700000000000000000000000000000000000000000000000000000000000000d800000000000000000000000000000000000000000000000000000000000000d900000000000000000000000000000000000000000000000000000000000000da00000000000000000000000000000000000000000000000000000000000000db00000000000000000000000000000000000000000000000000000000000000dc00000000000000000000000000000000000000000000000000000000000000dd00000000000000000000000000000000000000000000000000000000000000de00000000000000000000000000000000000000000000000000000000000000df00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000e100000000000000000000000000000000000000000000000000000000000000e200000000000000000000000000000000000000000000000000000000000000e300000000000000000000000000000000000000000000000000000000000000e400000000000000000000000000000000000000000000000000000000000000e500000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000e700000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000e900000000000000000000000000000000000000000000000000000000000000ea00000000000000000000000000000000000000000000000000000000000000eb00000000000000000000000000000000000000000000000000000000000000ec00000000000000000000000000000000000000000000000000000000000000ed00000000000000000000000000000000000000000000000000000000000000ee00000000000000000000000000000000000000000000000000000000000000ef00000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000f200000000000000000000000000000000000000000000000000000000000000f300000000000000000000000000000000000000000000000000000000000000f400000000000000000000000000000000000000000000000000000000000000f500000000000000000000000000000000000000000000000000000000000000f600000000000000000000000000000000000000000000000000000000000000f700000000000000000000000000000000000000000000000000000000000000f800000000000000000000000000000000000000000000000000000000000000f900000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fb00000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000fd00000000000000000000000000000000000000000000000000000000000000fe00000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000103000000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000010700000000000000000000000000000000000000000000000000000000000001080000000000000000000000000000000000000000000000000000000000000109000000000000000000000000000000000000000000000000000000000000010a000000000000000000000000000000000000000000000000000000000000010b000000000000000000000000000000000000000000000000000000000000010c000000000000000000000000000000000000000000000000000000000000010d000000000000000000000000000000000000000000000000000000000000010e000000000000000000000000000000000000000000000000000000000000010f0000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000011100000000000000000000000000000000000000000000000000000000000001120000000000000000000000000000000000000000000000000000000000000113000000000000000000000000000000000000000000000000000000000000011400000000000000000000000000000000000000000000000000000000000001150000000000000000000000000000000000000000000000000000000000000116000000000000000000000000000000000000000000000000000000000000011700000000000000000000000000000000000000000000000000000000000001180000000000000000000000000000000000000000000000000000000000000119000000000000000000000000000000000000000000000000000000000000011a000000000000000000000000000000000000000000000000000000000000011b000000000000000000000000000000000000000000000000000000000000011c000000000000000000000000000000000000000000000000000000000000011d000000000000000000000000000000000000000000000000000000000000011e000000000000000000000000000000000000000000000000000000000000011f0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012100000000000000000000000000000000000000000000000000000000000001220000000000000000000000000000000000000000000000000000000000000123000000000000000000000000000000000000000000000000000000000000012400000000000000000000000000000000000000000000000000000000000001250000000000000000000000000000000000000000000000000000000000000126000000000000000000000000000000000000000000000000000000000000012700000000000000000000000000000000000000000000000000000000000001280000000000000000000000000000000000000000000000000000000000000129000000000000000000000000000000000000000000000000000000000000012a000000000000000000000000000000000000000000000000000000000000012b000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000012d000000000000000000000000000000000000000000000000000000000000012e000000000000000000000000000000000000000000000000000000000000012f0000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000013100000000000000000000000000000000000000000000000000000000000001320000000000000000000000000000000000000000000000000000000000000133000000000000000000000000000000000000000000000000000000000000013400000000000000000000000000000000000000000000000000000000000001350000000000000000000000000000000000000000000000000000000000000136000000000000000000000000000000000000000000000000000000000000013700000000000000000000000000000000000000000000000000000000000001380000000000000000000000000000000000000000000000000000000000000139000000000000000000000000000000000000000000000000000000000000013a000000000000000000000000000000000000000000000000000000000000013b000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000013d000000000000000000000000000000000000000000000000000000000000013e000000000000000000000000000000000000000000000000000000000000013f0000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f0000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f000000000000000000000000000000000000000000000000000000000000019059d5401100000000", + "accounts": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000014", + "0x0000000000000000000000000000000000000000000000000000000000000015", + "0x0000000000000000000000000000000000000000000000000000000000000016", + "0x0000000000000000000000000000000000000000000000000000000000000017", + "0x0000000000000000000000000000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000019", + "0x000000000000000000000000000000000000000000000000000000000000001a", + "0x000000000000000000000000000000000000000000000000000000000000001b", + "0x000000000000000000000000000000000000000000000000000000000000001c", + "0x000000000000000000000000000000000000000000000000000000000000001d", + "0x000000000000000000000000000000000000000000000000000000000000001e", + "0x000000000000000000000000000000000000000000000000000000000000001f", + "0x0000000000000000000000000000000000000000000000000000000000000020", + "0x0000000000000000000000000000000000000000000000000000000000000021", + "0x0000000000000000000000000000000000000000000000000000000000000022", + "0x0000000000000000000000000000000000000000000000000000000000000023", + "0x0000000000000000000000000000000000000000000000000000000000000024", + "0x0000000000000000000000000000000000000000000000000000000000000025", + "0x0000000000000000000000000000000000000000000000000000000000000026", + "0x0000000000000000000000000000000000000000000000000000000000000027", + "0x0000000000000000000000000000000000000000000000000000000000000028", + "0x0000000000000000000000000000000000000000000000000000000000000029", + "0x000000000000000000000000000000000000000000000000000000000000002a", + "0x000000000000000000000000000000000000000000000000000000000000002b", + "0x000000000000000000000000000000000000000000000000000000000000002c", + "0x000000000000000000000000000000000000000000000000000000000000002d", + "0x000000000000000000000000000000000000000000000000000000000000002e", + "0x000000000000000000000000000000000000000000000000000000000000002f", + "0x0000000000000000000000000000000000000000000000000000000000000030", + "0x0000000000000000000000000000000000000000000000000000000000000031", + "0x0000000000000000000000000000000000000000000000000000000000000032", + "0x0000000000000000000000000000000000000000000000000000000000000033", + "0x0000000000000000000000000000000000000000000000000000000000000034", + "0x0000000000000000000000000000000000000000000000000000000000000035", + "0x0000000000000000000000000000000000000000000000000000000000000036", + "0x0000000000000000000000000000000000000000000000000000000000000037", + "0x0000000000000000000000000000000000000000000000000000000000000038", + "0x0000000000000000000000000000000000000000000000000000000000000039", + "0x000000000000000000000000000000000000000000000000000000000000003a", + "0x000000000000000000000000000000000000000000000000000000000000003b", + "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x000000000000000000000000000000000000000000000000000000000000003d", + "0x000000000000000000000000000000000000000000000000000000000000003e", + "0x000000000000000000000000000000000000000000000000000000000000003f", + "0x0000000000000000000000000000000000000000000000000000000000000040", + "0x0000000000000000000000000000000000000000000000000000000000000041", + "0x0000000000000000000000000000000000000000000000000000000000000042", + "0x0000000000000000000000000000000000000000000000000000000000000043", + "0x0000000000000000000000000000000000000000000000000000000000000044", + "0x0000000000000000000000000000000000000000000000000000000000000045", + "0x0000000000000000000000000000000000000000000000000000000000000046", + "0x0000000000000000000000000000000000000000000000000000000000000047", + "0x0000000000000000000000000000000000000000000000000000000000000048", + "0x0000000000000000000000000000000000000000000000000000000000000049", + "0x000000000000000000000000000000000000000000000000000000000000004a", + "0x000000000000000000000000000000000000000000000000000000000000004b", + "0x000000000000000000000000000000000000000000000000000000000000004c", + "0x000000000000000000000000000000000000000000000000000000000000004d", + "0x000000000000000000000000000000000000000000000000000000000000004e", + "0x000000000000000000000000000000000000000000000000000000000000004f", + "0x0000000000000000000000000000000000000000000000000000000000000050", + "0x0000000000000000000000000000000000000000000000000000000000000051", + "0x0000000000000000000000000000000000000000000000000000000000000052", + "0x0000000000000000000000000000000000000000000000000000000000000053", + "0x0000000000000000000000000000000000000000000000000000000000000054", + "0x0000000000000000000000000000000000000000000000000000000000000055", + "0x0000000000000000000000000000000000000000000000000000000000000056", + "0x0000000000000000000000000000000000000000000000000000000000000057", + "0x0000000000000000000000000000000000000000000000000000000000000058", + "0x0000000000000000000000000000000000000000000000000000000000000059", + "0x000000000000000000000000000000000000000000000000000000000000005a", + "0x000000000000000000000000000000000000000000000000000000000000005b", + "0x000000000000000000000000000000000000000000000000000000000000005c", + "0x000000000000000000000000000000000000000000000000000000000000005d", + "0x000000000000000000000000000000000000000000000000000000000000005e", + "0x000000000000000000000000000000000000000000000000000000000000005f", + "0x0000000000000000000000000000000000000000000000000000000000000060", + "0x0000000000000000000000000000000000000000000000000000000000000061", + "0x0000000000000000000000000000000000000000000000000000000000000062", + "0x0000000000000000000000000000000000000000000000000000000000000063", + "0x0000000000000000000000000000000000000000000000000000000000000064", + "0x0000000000000000000000000000000000000000000000000000000000000065", + "0x0000000000000000000000000000000000000000000000000000000000000066", + "0x0000000000000000000000000000000000000000000000000000000000000067", + "0x0000000000000000000000000000000000000000000000000000000000000068", + "0x0000000000000000000000000000000000000000000000000000000000000069", + "0x000000000000000000000000000000000000000000000000000000000000006a", + "0x000000000000000000000000000000000000000000000000000000000000006b", + "0x000000000000000000000000000000000000000000000000000000000000006c", + "0x000000000000000000000000000000000000000000000000000000000000006d", + "0x000000000000000000000000000000000000000000000000000000000000006e", + "0x000000000000000000000000000000000000000000000000000000000000006f", + "0x0000000000000000000000000000000000000000000000000000000000000070", + "0x0000000000000000000000000000000000000000000000000000000000000071", + "0x0000000000000000000000000000000000000000000000000000000000000072", + "0x0000000000000000000000000000000000000000000000000000000000000073", + "0x0000000000000000000000000000000000000000000000000000000000000074", + "0x0000000000000000000000000000000000000000000000000000000000000075", + "0x0000000000000000000000000000000000000000000000000000000000000076", + "0x0000000000000000000000000000000000000000000000000000000000000077", + "0x0000000000000000000000000000000000000000000000000000000000000078", + "0x0000000000000000000000000000000000000000000000000000000000000079", + "0x000000000000000000000000000000000000000000000000000000000000007a", + "0x000000000000000000000000000000000000000000000000000000000000007b", + "0x000000000000000000000000000000000000000000000000000000000000007c", + "0x000000000000000000000000000000000000000000000000000000000000007d", + "0x000000000000000000000000000000000000000000000000000000000000007e", + "0x000000000000000000000000000000000000000000000000000000000000007f", + "0x0000000000000000000000000000000000000000000000000000000000000080", + "0x0000000000000000000000000000000000000000000000000000000000000081", + "0x0000000000000000000000000000000000000000000000000000000000000082", + "0x0000000000000000000000000000000000000000000000000000000000000083", + "0x0000000000000000000000000000000000000000000000000000000000000084", + "0x0000000000000000000000000000000000000000000000000000000000000085", + "0x0000000000000000000000000000000000000000000000000000000000000086", + "0x0000000000000000000000000000000000000000000000000000000000000087", + "0x0000000000000000000000000000000000000000000000000000000000000088", + "0x0000000000000000000000000000000000000000000000000000000000000089", + "0x000000000000000000000000000000000000000000000000000000000000008a", + "0x000000000000000000000000000000000000000000000000000000000000008b", + "0x000000000000000000000000000000000000000000000000000000000000008c", + "0x000000000000000000000000000000000000000000000000000000000000008d", + "0x000000000000000000000000000000000000000000000000000000000000008e", + "0x000000000000000000000000000000000000000000000000000000000000008f", + "0x0000000000000000000000000000000000000000000000000000000000000090", + "0x0000000000000000000000000000000000000000000000000000000000000091", + "0x0000000000000000000000000000000000000000000000000000000000000092", + "0x0000000000000000000000000000000000000000000000000000000000000093", + "0x0000000000000000000000000000000000000000000000000000000000000094", + "0x0000000000000000000000000000000000000000000000000000000000000095", + "0x0000000000000000000000000000000000000000000000000000000000000096", + "0x0000000000000000000000000000000000000000000000000000000000000097", + "0x0000000000000000000000000000000000000000000000000000000000000098", + "0x0000000000000000000000000000000000000000000000000000000000000099", + "0x000000000000000000000000000000000000000000000000000000000000009a", + "0x000000000000000000000000000000000000000000000000000000000000009b", + "0x000000000000000000000000000000000000000000000000000000000000009c", + "0x000000000000000000000000000000000000000000000000000000000000009d", + "0x000000000000000000000000000000000000000000000000000000000000009e", + "0x000000000000000000000000000000000000000000000000000000000000009f", + "0x00000000000000000000000000000000000000000000000000000000000000a0", + "0x00000000000000000000000000000000000000000000000000000000000000a1", + "0x00000000000000000000000000000000000000000000000000000000000000a2", + "0x00000000000000000000000000000000000000000000000000000000000000a3", + "0x00000000000000000000000000000000000000000000000000000000000000a4", + "0x00000000000000000000000000000000000000000000000000000000000000a5", + "0x00000000000000000000000000000000000000000000000000000000000000a6", + "0x00000000000000000000000000000000000000000000000000000000000000a7", + "0x00000000000000000000000000000000000000000000000000000000000000a8", + "0x00000000000000000000000000000000000000000000000000000000000000a9", + "0x00000000000000000000000000000000000000000000000000000000000000aa", + "0x00000000000000000000000000000000000000000000000000000000000000ab", + "0x00000000000000000000000000000000000000000000000000000000000000ac", + "0x00000000000000000000000000000000000000000000000000000000000000ad", + "0x00000000000000000000000000000000000000000000000000000000000000ae", + "0x00000000000000000000000000000000000000000000000000000000000000af", + "0x00000000000000000000000000000000000000000000000000000000000000b0", + "0x00000000000000000000000000000000000000000000000000000000000000b1", + "0x00000000000000000000000000000000000000000000000000000000000000b2", + "0x00000000000000000000000000000000000000000000000000000000000000b3", + "0x00000000000000000000000000000000000000000000000000000000000000b4", + "0x00000000000000000000000000000000000000000000000000000000000000b5", + "0x00000000000000000000000000000000000000000000000000000000000000b6", + "0x00000000000000000000000000000000000000000000000000000000000000b7", + "0x00000000000000000000000000000000000000000000000000000000000000b8", + "0x00000000000000000000000000000000000000000000000000000000000000b9", + "0x00000000000000000000000000000000000000000000000000000000000000ba", + "0x00000000000000000000000000000000000000000000000000000000000000bb", + "0x00000000000000000000000000000000000000000000000000000000000000bc", + "0x00000000000000000000000000000000000000000000000000000000000000bd", + "0x00000000000000000000000000000000000000000000000000000000000000be", + "0x00000000000000000000000000000000000000000000000000000000000000bf", + "0x00000000000000000000000000000000000000000000000000000000000000c0", + "0x00000000000000000000000000000000000000000000000000000000000000c1", + "0x00000000000000000000000000000000000000000000000000000000000000c2", + "0x00000000000000000000000000000000000000000000000000000000000000c3", + "0x00000000000000000000000000000000000000000000000000000000000000c4", + "0x00000000000000000000000000000000000000000000000000000000000000c5", + "0x00000000000000000000000000000000000000000000000000000000000000c6", + "0x00000000000000000000000000000000000000000000000000000000000000c7", + "0x00000000000000000000000000000000000000000000000000000000000000c8", + "0x00000000000000000000000000000000000000000000000000000000000000c9", + "0x00000000000000000000000000000000000000000000000000000000000000ca", + "0x00000000000000000000000000000000000000000000000000000000000000cb", + "0x00000000000000000000000000000000000000000000000000000000000000cc", + "0x00000000000000000000000000000000000000000000000000000000000000cd", + "0x00000000000000000000000000000000000000000000000000000000000000ce", + "0x00000000000000000000000000000000000000000000000000000000000000cf", + "0x00000000000000000000000000000000000000000000000000000000000000d0", + "0x00000000000000000000000000000000000000000000000000000000000000d1", + "0x00000000000000000000000000000000000000000000000000000000000000d2", + "0x00000000000000000000000000000000000000000000000000000000000000d3", + "0x00000000000000000000000000000000000000000000000000000000000000d4", + "0x00000000000000000000000000000000000000000000000000000000000000d5", + "0x00000000000000000000000000000000000000000000000000000000000000d6", + "0x00000000000000000000000000000000000000000000000000000000000000d7", + "0x00000000000000000000000000000000000000000000000000000000000000d8", + "0x00000000000000000000000000000000000000000000000000000000000000d9", + "0x00000000000000000000000000000000000000000000000000000000000000da", + "0x00000000000000000000000000000000000000000000000000000000000000db", + "0x00000000000000000000000000000000000000000000000000000000000000dc", + "0x00000000000000000000000000000000000000000000000000000000000000dd", + "0x00000000000000000000000000000000000000000000000000000000000000de", + "0x00000000000000000000000000000000000000000000000000000000000000df", + "0x00000000000000000000000000000000000000000000000000000000000000e0", + "0x00000000000000000000000000000000000000000000000000000000000000e1", + "0x00000000000000000000000000000000000000000000000000000000000000e2", + "0x00000000000000000000000000000000000000000000000000000000000000e3", + "0x00000000000000000000000000000000000000000000000000000000000000e4", + "0x00000000000000000000000000000000000000000000000000000000000000e5", + "0x00000000000000000000000000000000000000000000000000000000000000e6", + "0x00000000000000000000000000000000000000000000000000000000000000e7", + "0x00000000000000000000000000000000000000000000000000000000000000e8", + "0x00000000000000000000000000000000000000000000000000000000000000e9", + "0x00000000000000000000000000000000000000000000000000000000000000ea", + "0x00000000000000000000000000000000000000000000000000000000000000eb", + "0x00000000000000000000000000000000000000000000000000000000000000ec", + "0x00000000000000000000000000000000000000000000000000000000000000ed", + "0x00000000000000000000000000000000000000000000000000000000000000ee", + "0x00000000000000000000000000000000000000000000000000000000000000ef", + "0x00000000000000000000000000000000000000000000000000000000000000f0", + "0x00000000000000000000000000000000000000000000000000000000000000f1", + "0x00000000000000000000000000000000000000000000000000000000000000f2", + "0x00000000000000000000000000000000000000000000000000000000000000f3", + "0x00000000000000000000000000000000000000000000000000000000000000f4", + "0x00000000000000000000000000000000000000000000000000000000000000f5", + "0x00000000000000000000000000000000000000000000000000000000000000f6", + "0x00000000000000000000000000000000000000000000000000000000000000f7", + "0x00000000000000000000000000000000000000000000000000000000000000f8", + "0x00000000000000000000000000000000000000000000000000000000000000f9", + "0x00000000000000000000000000000000000000000000000000000000000000fa", + "0x00000000000000000000000000000000000000000000000000000000000000fb", + "0x00000000000000000000000000000000000000000000000000000000000000fc", + "0x00000000000000000000000000000000000000000000000000000000000000fd", + "0x00000000000000000000000000000000000000000000000000000000000000fe", + "0x00000000000000000000000000000000000000000000000000000000000000ff", + "0x0000000000000000000000000000000000000000000000000000000000000100", + "0x0000000000000000000000000000000000000000000000000000000000000101", + "0x0000000000000000000000000000000000000000000000000000000000000102", + "0x0000000000000000000000000000000000000000000000000000000000000103", + "0x0000000000000000000000000000000000000000000000000000000000000104", + "0x0000000000000000000000000000000000000000000000000000000000000105", + "0x0000000000000000000000000000000000000000000000000000000000000106", + "0x0000000000000000000000000000000000000000000000000000000000000107", + "0x0000000000000000000000000000000000000000000000000000000000000108", + "0x0000000000000000000000000000000000000000000000000000000000000109", + "0x000000000000000000000000000000000000000000000000000000000000010a", + "0x000000000000000000000000000000000000000000000000000000000000010b", + "0x000000000000000000000000000000000000000000000000000000000000010c", + "0x000000000000000000000000000000000000000000000000000000000000010d", + "0x000000000000000000000000000000000000000000000000000000000000010e", + "0x000000000000000000000000000000000000000000000000000000000000010f", + "0x0000000000000000000000000000000000000000000000000000000000000110", + "0x0000000000000000000000000000000000000000000000000000000000000111", + "0x0000000000000000000000000000000000000000000000000000000000000112", + "0x0000000000000000000000000000000000000000000000000000000000000113", + "0x0000000000000000000000000000000000000000000000000000000000000114", + "0x0000000000000000000000000000000000000000000000000000000000000115", + "0x0000000000000000000000000000000000000000000000000000000000000116", + "0x0000000000000000000000000000000000000000000000000000000000000117", + "0x0000000000000000000000000000000000000000000000000000000000000118", + "0x0000000000000000000000000000000000000000000000000000000000000119", + "0x000000000000000000000000000000000000000000000000000000000000011a", + "0x000000000000000000000000000000000000000000000000000000000000011b", + "0x000000000000000000000000000000000000000000000000000000000000011c", + "0x000000000000000000000000000000000000000000000000000000000000011d", + "0x000000000000000000000000000000000000000000000000000000000000011e", + "0x000000000000000000000000000000000000000000000000000000000000011f", + "0x0000000000000000000000000000000000000000000000000000000000000120", + "0x0000000000000000000000000000000000000000000000000000000000000121", + "0x0000000000000000000000000000000000000000000000000000000000000122", + "0x0000000000000000000000000000000000000000000000000000000000000123", + "0x0000000000000000000000000000000000000000000000000000000000000124", + "0x0000000000000000000000000000000000000000000000000000000000000125", + "0x0000000000000000000000000000000000000000000000000000000000000126", + "0x0000000000000000000000000000000000000000000000000000000000000127", + "0x0000000000000000000000000000000000000000000000000000000000000128", + "0x0000000000000000000000000000000000000000000000000000000000000129", + "0x000000000000000000000000000000000000000000000000000000000000012a", + "0x000000000000000000000000000000000000000000000000000000000000012b", + "0x000000000000000000000000000000000000000000000000000000000000012c", + "0x000000000000000000000000000000000000000000000000000000000000012d", + "0x000000000000000000000000000000000000000000000000000000000000012e", + "0x000000000000000000000000000000000000000000000000000000000000012f", + "0x0000000000000000000000000000000000000000000000000000000000000130", + "0x0000000000000000000000000000000000000000000000000000000000000131", + "0x0000000000000000000000000000000000000000000000000000000000000132", + "0x0000000000000000000000000000000000000000000000000000000000000133", + "0x0000000000000000000000000000000000000000000000000000000000000134", + "0x0000000000000000000000000000000000000000000000000000000000000135", + "0x0000000000000000000000000000000000000000000000000000000000000136", + "0x0000000000000000000000000000000000000000000000000000000000000137", + "0x0000000000000000000000000000000000000000000000000000000000000138", + "0x0000000000000000000000000000000000000000000000000000000000000139", + "0x000000000000000000000000000000000000000000000000000000000000013a", + "0x000000000000000000000000000000000000000000000000000000000000013b", + "0x000000000000000000000000000000000000000000000000000000000000013c", + "0x000000000000000000000000000000000000000000000000000000000000013d", + "0x000000000000000000000000000000000000000000000000000000000000013e", + "0x000000000000000000000000000000000000000000000000000000000000013f", + "0x0000000000000000000000000000000000000000000000000000000000000140", + "0x0000000000000000000000000000000000000000000000000000000000000141", + "0x0000000000000000000000000000000000000000000000000000000000000142", + "0x0000000000000000000000000000000000000000000000000000000000000143", + "0x0000000000000000000000000000000000000000000000000000000000000144", + "0x0000000000000000000000000000000000000000000000000000000000000145", + "0x0000000000000000000000000000000000000000000000000000000000000146", + "0x0000000000000000000000000000000000000000000000000000000000000147", + "0x0000000000000000000000000000000000000000000000000000000000000148", + "0x0000000000000000000000000000000000000000000000000000000000000149", + "0x000000000000000000000000000000000000000000000000000000000000014a", + "0x000000000000000000000000000000000000000000000000000000000000014b", + "0x000000000000000000000000000000000000000000000000000000000000014c", + "0x000000000000000000000000000000000000000000000000000000000000014d", + "0x000000000000000000000000000000000000000000000000000000000000014e", + "0x000000000000000000000000000000000000000000000000000000000000014f", + "0x0000000000000000000000000000000000000000000000000000000000000150", + "0x0000000000000000000000000000000000000000000000000000000000000151", + "0x0000000000000000000000000000000000000000000000000000000000000152", + "0x0000000000000000000000000000000000000000000000000000000000000153", + "0x0000000000000000000000000000000000000000000000000000000000000154", + "0x0000000000000000000000000000000000000000000000000000000000000155", + "0x0000000000000000000000000000000000000000000000000000000000000156", + "0x0000000000000000000000000000000000000000000000000000000000000157", + "0x0000000000000000000000000000000000000000000000000000000000000158", + "0x0000000000000000000000000000000000000000000000000000000000000159", + "0x000000000000000000000000000000000000000000000000000000000000015a", + "0x000000000000000000000000000000000000000000000000000000000000015b", + "0x000000000000000000000000000000000000000000000000000000000000015c", + "0x000000000000000000000000000000000000000000000000000000000000015d", + "0x000000000000000000000000000000000000000000000000000000000000015e", + "0x000000000000000000000000000000000000000000000000000000000000015f", + "0x0000000000000000000000000000000000000000000000000000000000000160", + "0x0000000000000000000000000000000000000000000000000000000000000161", + "0x0000000000000000000000000000000000000000000000000000000000000162", + "0x0000000000000000000000000000000000000000000000000000000000000163", + "0x0000000000000000000000000000000000000000000000000000000000000164", + "0x0000000000000000000000000000000000000000000000000000000000000165", + "0x0000000000000000000000000000000000000000000000000000000000000166", + "0x0000000000000000000000000000000000000000000000000000000000000167", + "0x0000000000000000000000000000000000000000000000000000000000000168", + "0x0000000000000000000000000000000000000000000000000000000000000169", + "0x000000000000000000000000000000000000000000000000000000000000016a", + "0x000000000000000000000000000000000000000000000000000000000000016b", + "0x000000000000000000000000000000000000000000000000000000000000016c", + "0x000000000000000000000000000000000000000000000000000000000000016d", + "0x000000000000000000000000000000000000000000000000000000000000016e", + "0x000000000000000000000000000000000000000000000000000000000000016f", + "0x0000000000000000000000000000000000000000000000000000000000000170", + "0x0000000000000000000000000000000000000000000000000000000000000171", + "0x0000000000000000000000000000000000000000000000000000000000000172", + "0x0000000000000000000000000000000000000000000000000000000000000173", + "0x0000000000000000000000000000000000000000000000000000000000000174", + "0x0000000000000000000000000000000000000000000000000000000000000175", + "0x0000000000000000000000000000000000000000000000000000000000000176", + "0x0000000000000000000000000000000000000000000000000000000000000177", + "0x0000000000000000000000000000000000000000000000000000000000000178", + "0x0000000000000000000000000000000000000000000000000000000000000179", + "0x000000000000000000000000000000000000000000000000000000000000017a", + "0x000000000000000000000000000000000000000000000000000000000000017b", + "0x000000000000000000000000000000000000000000000000000000000000017c", + "0x000000000000000000000000000000000000000000000000000000000000017d", + "0x000000000000000000000000000000000000000000000000000000000000017e", + "0x000000000000000000000000000000000000000000000000000000000000017f", + "0x0000000000000000000000000000000000000000000000000000000000000180", + "0x0000000000000000000000000000000000000000000000000000000000000181", + "0x0000000000000000000000000000000000000000000000000000000000000182", + "0x0000000000000000000000000000000000000000000000000000000000000183", + "0x0000000000000000000000000000000000000000000000000000000000000184", + "0x0000000000000000000000000000000000000000000000000000000000000185", + "0x0000000000000000000000000000000000000000000000000000000000000186", + "0x0000000000000000000000000000000000000000000000000000000000000187", + "0x0000000000000000000000000000000000000000000000000000000000000188", + "0x0000000000000000000000000000000000000000000000000000000000000189", + "0x000000000000000000000000000000000000000000000000000000000000018a", + "0x000000000000000000000000000000000000000000000000000000000000018b", + "0x000000000000000000000000000000000000000000000000000000000000018c", + "0x000000000000000000000000000000000000000000000000000000000000018d", + "0x000000000000000000000000000000000000000000000000000000000000018e", + "0x000000000000000000000000000000000000000000000000000000000000018f", + "0x0000000000000000000000000000000000000000000000000000000000000190" + ], + "epoch": 289461593 +} diff --git a/contracts/test/snowbridge-data/test_vector_message_validator_50.json b/contracts/test/snowbridge-data/test_vector_message_validator_50.json new file mode 100644 index 000000000..121a1af87 --- /dev/null +++ b/contracts/test/snowbridge-data/test_vector_message_validator_50.json @@ -0,0 +1,56 @@ +{ + "payload": "0x701500380000c8000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001f0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000032f055885f94010000", + "accounts": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000014", + "0x0000000000000000000000000000000000000000000000000000000000000015", + "0x0000000000000000000000000000000000000000000000000000000000000016", + "0x0000000000000000000000000000000000000000000000000000000000000017", + "0x0000000000000000000000000000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000019", + "0x000000000000000000000000000000000000000000000000000000000000001a", + "0x000000000000000000000000000000000000000000000000000000000000001b", + "0x000000000000000000000000000000000000000000000000000000000000001c", + "0x000000000000000000000000000000000000000000000000000000000000001d", + "0x000000000000000000000000000000000000000000000000000000000000001e", + "0x000000000000000000000000000000000000000000000000000000000000001f", + "0x0000000000000000000000000000000000000000000000000000000000000020", + "0x0000000000000000000000000000000000000000000000000000000000000021", + "0x0000000000000000000000000000000000000000000000000000000000000022", + "0x0000000000000000000000000000000000000000000000000000000000000023", + "0x0000000000000000000000000000000000000000000000000000000000000024", + "0x0000000000000000000000000000000000000000000000000000000000000025", + "0x0000000000000000000000000000000000000000000000000000000000000026", + "0x0000000000000000000000000000000000000000000000000000000000000027", + "0x0000000000000000000000000000000000000000000000000000000000000028", + "0x0000000000000000000000000000000000000000000000000000000000000029", + "0x000000000000000000000000000000000000000000000000000000000000002a", + "0x000000000000000000000000000000000000000000000000000000000000002b", + "0x000000000000000000000000000000000000000000000000000000000000002c", + "0x000000000000000000000000000000000000000000000000000000000000002d", + "0x000000000000000000000000000000000000000000000000000000000000002e", + "0x000000000000000000000000000000000000000000000000000000000000002f", + "0x0000000000000000000000000000000000000000000000000000000000000030", + "0x0000000000000000000000000000000000000000000000000000000000000031", + "0x0000000000000000000000000000000000000000000000000000000000000032" + ], + "epoch": 1736769558000 + }