diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d8d2ba06..63221122 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -44,6 +44,8 @@ jobs: uses: ./.github/workflows/task-rust-tests.yml contract-tests: uses: ./.github/workflows/task-foundry-tests.yml + storage-layout: + uses: ./.github/workflows/task-storage-layout.yml rust-lint: needs: [warm-sccache] uses: ./.github/workflows/task-rust-lint.yml diff --git a/.github/workflows/task-e2e.yml b/.github/workflows/task-e2e.yml index 694b0906..dfd8cee6 100644 --- a/.github/workflows/task-e2e.yml +++ b/.github/workflows/task-e2e.yml @@ -118,23 +118,6 @@ jobs: key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - - name: Cache Foundry libraries - uses: actions/cache/restore@v4 - with: - path: ../contracts/lib - key: ${{ runner.os }}-foundry-libs-${{ hashFiles('.gitmodules') }} - restore-keys: | - ${{ runner.os }}-foundry-libs- - - - name: Cache Foundry build artifacts - uses: actions/cache/restore@v4 - with: - path: | - ../contracts/out - ../contracts/cache - key: ${{ runner.os }}-foundry-build-${{ hashFiles('contracts/foundry.toml', 'contracts/**/*.sol') }} - restore-keys: | - ${{ runner.os }}-foundry-build- - uses: docker/login-action@v3 with: registry: ghcr.io diff --git a/.github/workflows/task-foundry-tests.yml b/.github/workflows/task-foundry-tests.yml index c6bc6d81..81288ee6 100644 --- a/.github/workflows/task-foundry-tests.yml +++ b/.github/workflows/task-foundry-tests.yml @@ -38,16 +38,6 @@ jobs: with: version: v1.4.3 - - name: Cache Foundry build artifacts - uses: actions/cache@v4 - with: - path: | - contracts/out - contracts/cache - key: ${{ runner.os }}-foundry-build-${{ hashFiles('contracts/foundry.toml', 'contracts/**/*.sol') }} - restore-keys: | - ${{ runner.os }}-foundry-build- - - run: forge --version - run: forge fmt --check - run: forge build --sizes diff --git a/.github/workflows/task-storage-layout.yml b/.github/workflows/task-storage-layout.yml new file mode 100644 index 00000000..2a1a78a5 --- /dev/null +++ b/.github/workflows/task-storage-layout.yml @@ -0,0 +1,51 @@ +# Storage Layout Check: Validates storage layout for upgradeable contracts +# +# Overview: +# 1. Compares current storage layout against committed snapshot +# 2. Runs upgrade simulation tests to verify state preservation + +name: Storage Layout Check + +on: + workflow_dispatch: + workflow_call: + +# Explicit minimal permissions +permissions: + contents: read + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + name: Storage Layout + runs-on: ubuntu-latest + defaults: + run: + working-directory: contracts + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.4.3 + + - name: Build contracts + run: forge build --extra-output storageLayout + + - name: Negative check storage layout (should fail) + run: | + chmod +x scripts/check-storage-layout-negative.sh + ./scripts/check-storage-layout-negative.sh + + - name: Check storage layout + run: | + chmod +x scripts/check-storage-layout.sh + ./scripts/check-storage-layout.sh + + - name: Run upgrade simulation tests + run: forge test --match-contract StorageLayoutTest -vvv diff --git a/biome.json b/biome.json index 9c5ae7a4..aed14936 100644 --- a/biome.json +++ b/biome.json @@ -8,6 +8,7 @@ "**/*.yml", "**/*.md", "!node_modules/*", + "!**/moonwall/**/*", "!target/*", "!**/tmp/*", "!**/*.spec.json", diff --git a/contracts/README.md b/contracts/README.md index 9a737048..0d4042d2 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,6 +1,6 @@ # DataHaven AVS Smart Contracts -Implements the Actively Validated Service (AVS) logic for DataHaven, secured by EigenLayer. These contracts manage operator registration, handle cross-chain rewards via Snowbridge, and enforce slashing with a veto period. +Implements the Actively Validated Service (AVS) logic for DataHaven, secured by EigenLayer. These contracts manage operator registration, handle cross-chain rewards via Snowbridge, and enforce slashing. ## Project Structure @@ -65,6 +65,6 @@ Supported networks: `hoodi` (no mainnet config yet). Artifacts → `contracts/de 1. **Registration**: Validators register with EigenLayer via `DataHavenServiceManager`. 2. **Performance Tracking**: DataHaven computes reward points and sends a Merkle root to `RewardsRegistry` on Ethereum via Snowbridge. 3. **Rewards Claims**: Validators claim rewards on Ethereum from `RewardsRegistry` using Merkle proofs. -4. **Slashing**: Misbehavior triggers slashing (subject to veto period). +4. **Slashing**: Misbehavior triggers slashing. See `test/README.md` for full network integration tests. diff --git a/contracts/config/anvil.json b/contracts/config/anvil.json index 16652567..8e3796c3 100644 --- a/contracts/config/anvil.json +++ b/contracts/config/anvil.json @@ -21,14 +21,13 @@ "rewardsCoordinatorInitPausedStatus": 0, "allocationManagerInitPausedStatus": 0, "deallocationDelay": 50, - "allocationConfigurationDelay": 75, + "allocationConfigurationDelay": 0, "beaconChainGenesisTimestamp": 1695902400 }, "avs": { "avsOwner": "0x976EA74026E726554dB657fA54763abd0C3a0aa9", "rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", - "vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", - "vetoWindowBlocks": 100, + "validatorSetSubmitter": "0x976EA74026E726554dB657fA54763abd0C3a0aa9", "validatorsStrategies": [] }, "snowbridge": { @@ -37,10 +36,12 @@ "minNumRequiredSignatures": 2, "startBlock": 1, "rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000", + "initialValidatorSetId": 0, "initialValidatorHashes": [ "0xaeb47a269393297f4b0a3c9c9cfd00c7a4195255274cf39d83dabc2fcc9ff3d7", "0xf68aec7304bf37f340dae2ea20fb5271ee28a3128812b84a615da4789e458bde" ], + "nextValidatorSetId": 1, "nextValidatorHashes": [ "0xaeb47a269393297f4b0a3c9c9cfd00c7a4195255274cf39d83dabc2fcc9ff3d7", "0xf68aec7304bf37f340dae2ea20fb5271ee28a3128812b84a615da4789e458bde" diff --git a/contracts/config/example.jsonc b/contracts/config/example.jsonc index 334abd2a..e57c1ec7 100644 --- a/contracts/config/example.jsonc +++ b/contracts/config/example.jsonc @@ -69,12 +69,20 @@ /// This is for the EigenLayer rewards distribution way, using the RewardsCoordinator. /// But for now, we're not using it, and instead sending the rewards directly. "rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", - /// The address of the account that is a member of the Veto Committee for vetoing slashing. - "vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", - /// The number of blocks that the Veto Committee will have to submit a veto. - "vetoWindowBlocks": 100, /// The EigenLayer strategy addresses for the Validators to stake into. - "validatorsStrategies": [] + /// The beaconChainETHStrategy is a virtual address representing native beacon chain ETH. + /// All networks: + /// - beaconChainETH: 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0 (virtual, same on all networks) + /// Hoodi testnet strategies: + /// - stETH: 0xf8a1a66130d614c7360e868576d5e59203475fe0 + /// - WETH: 0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d + /// Mainnet strategies: + /// - stETH: 0x93c4b944D05dfe6df7645A86cd2206016c51564D + /// - rETH: 0x1BeE69b7dFFfA4E2d53C2a2Df135C388AD25dCD2 + /// - cbETH: 0x54945180dB7943c0ed0FEE7EdaB2Bd24620256bc + "validatorsStrategies": [ + "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0" + ] }, "snowbridge": { /// Minimum delay in number of blocks that a relayer must wait between calling @@ -86,18 +94,27 @@ /// they desire. "randaoCommitExpiration": 24, /// The minimum number of required signatures for a Randao commit to be valid. + /// Auto-calculated by update-beefy-checkpoint as ceil(validators * 2/3) for BFT security. "minNumRequiredSignatures": 2, - /// Initial BEEFY block number. + /// Initial BEEFY block number. Set to latest finalized block by update-beefy-checkpoint. + /// The BeefyClient will only accept BEEFY commitments with block numbers > startBlock. "startBlock": 1, /// The origin linked to the Rewards Agent, the Agent contract who's allowed to submit /// new reward merkle roots to the RewardsRegistry contract. "rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000", + /// The BEEFY validator set ID for the initial validators. + /// This is fetched from Beefy.ValidatorSetId on the DataHaven chain. + "initialValidatorSetId": 0, /// The initial validator hashes for the BEEFY light client. + /// Each hash is keccak256(ethereum_address) derived from the BEEFY authority public keys. "initialValidatorHashes": [ "0x8626f6940e2eb28930efb4cef49b2d1f2c9c1199914b9e5506744e80bd0fd33d", "0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e" ], + /// The BEEFY validator set ID for the next validators (initialValidatorSetId + 1). + "nextValidatorSetId": 1, /// The next validator hashes for the BEEFY light client. + /// Each hash is keccak256(ethereum_address) derived from the BEEFY authority public keys. "nextValidatorHashes": [ "0x8626f6940e2eb28930efb4cef49b2d1f2c9c1199914b9e5506744e80bd0fd33d", "0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e" diff --git a/contracts/config/mainnet-ethereum.json b/contracts/config/mainnet-ethereum.json new file mode 100644 index 00000000..5a0e13fb --- /dev/null +++ b/contracts/config/mainnet-ethereum.json @@ -0,0 +1,52 @@ +{ + "eigenLayer": { + "pausers": [], + "unpauser": "0x0000000000000000000000000000000000000000", + "rewardsUpdater": "0x0000000000000000000000000000000000000000", + "calculationIntervalSeconds": 86400, + "maxRewardsDuration": 6048000, + "maxRetroactiveLength": 7776000, + "maxFutureLength": 2592000, + "genesisRewardsTimestamp": 1710979200, + "activationDelay": 7200, + "globalCommissionBips": 1000, + "executorMultisig": "0x0000000000000000000000000000000000000000", + "operationsMultisig": "0x0000000000000000000000000000000000000000", + "minWithdrawalDelayBlocks": 50400, + "delegationInitPausedStatus": 0, + "eigenPodManagerInitPausedStatus": 0, + "rewardsCoordinatorInitPausedStatus": 0, + "allocationManagerInitPausedStatus": 0, + "deallocationDelay": 100800, + "allocationConfigurationDelay": 1200, + "beaconChainGenesisTimestamp": 1606824023, + "delegationManager": "0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A", + "strategyManager": "0x858646372CC42E1A627fcE94aa7A7033e7CF075A", + "eigenPodManager": "0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338", + "avsDirectory": "0x135dda560e946695d6f155dacafc6f1f25c1f5af", + "rewardsCoordinator": "0x7750d328b314EfFa365A0402CcfD489B80B0adda", + "allocationManager": "0x948a420b8CC1d6BFd0B6087C2E7c344a2CD0bc39", + "permissionController": "0x25E5F8B1E7aDf44518d35D5B2271f114e081f0E5" + }, + "avs": { + "avsOwner": "0x0000000000000000000000000000000000000000", + "rewardsInitiator": "0x0000000000000000000000000000000000000000", + "validatorsStrategies": [ + "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0", + "0x93c4b944D05dfe6df7645A86cd2206016c51564D", + "0x1BeE69b7dFFfA4E2d53C2a2Df135C388AD25dCD2", + "0x54945180dB7943c0ed0FEE7EdaB2Bd24620256bc" + ] + }, + "snowbridge": { + "randaoCommitDelay": 4, + "randaoCommitExpiration": 24, + "minNumRequiredSignatures": 16, + "startBlock": 1, + "rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000", + "initialValidatorSetId": 0, + "initialValidatorHashes": [], + "nextValidatorSetId": 1, + "nextValidatorHashes": [] + } +} diff --git a/contracts/config/hoodi.json b/contracts/config/stagenet-hoodi.json similarity index 62% rename from contracts/config/hoodi.json rename to contracts/config/stagenet-hoodi.json index 02882a2d..a79ac73a 100644 --- a/contracts/config/hoodi.json +++ b/contracts/config/stagenet-hoodi.json @@ -27,29 +27,37 @@ "eigenPodManager": "0xcd1442415Fc5C29Aa848A49d2e232720BE07976c", "avsDirectory": "0xD58f6844f79eB1fbd9f7091d05f7cb30d3363926", "rewardsCoordinator": "0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7", - "allocationManager": "0x95a7431400F362F3647a69535C5666cA0133CAA0", + "allocationManager": "0x95a7431400F362F3647a69535C5666cA0133CAA0", "permissionController": "0xdcCF401fD121d8C542E96BC1d0078884422aFAD2" }, "avs": { "avsOwner": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", "rewardsInitiator": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", - "vetoCommitteeMember": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", - "vetoWindowBlocks": 100, - "validatorsStrategies": [] + "validatorsStrategies": [ + "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0", + "0xf8a1a66130d614c7360e868576d5e59203475fe0", + "0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d" + ] }, "snowbridge": { "randaoCommitDelay": 4, "randaoCommitExpiration": 24, - "minNumRequiredSignatures": 2, - "startBlock": 1, - "rewardsMessageOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000", + "minNumRequiredSignatures": 3, + "startBlock": 1303065, + "rewardsMessageOrigin": "0x56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd", + "initialValidatorSetId": 2186, "initialValidatorHashes": [ - "0xaeb47a269393297f4b0a3c9c9cfd00c7a4195255274cf39d83dabc2fcc9ff3d7", - "0xf68aec7304bf37f340dae2ea20fb5271ee28a3128812b84a615da4789e458bde" + "0x07ce4f2cd558f4d4b529a3362b6ff7d616ca0893b53252dc62829b8218ea5c10", + "0xaea5344f086d3be7c94cf3a47436bcbb98de23cf1ee773a9180cfecab0453a50", + "0xcd3a33755b27fe810dfb780b3f1df1c25efa1bb826ca618e41022fa900876087", + "0x4f4ce8cad711a4b33d15095091f8a98eaf9bfd1b39a9159e605cf5d6783cc667" ], + "nextValidatorSetId": 2187, "nextValidatorHashes": [ - "0xaeb47a269393297f4b0a3c9c9cfd00c7a4195255274cf39d83dabc2fcc9ff3d7", - "0xf68aec7304bf37f340dae2ea20fb5271ee28a3128812b84a615da4789e458bde" + "0x07ce4f2cd558f4d4b529a3362b6ff7d616ca0893b53252dc62829b8218ea5c10", + "0xaea5344f086d3be7c94cf3a47436bcbb98de23cf1ee773a9180cfecab0453a50", + "0xcd3a33755b27fe810dfb780b3f1df1c25efa1bb826ca618e41022fa900876087", + "0x4f4ce8cad711a4b33d15095091f8a98eaf9bfd1b39a9159e605cf5d6783cc667" ] } -} \ No newline at end of file +} diff --git a/contracts/config/testnet-hoodi.json b/contracts/config/testnet-hoodi.json new file mode 100644 index 00000000..1aa56fee --- /dev/null +++ b/contracts/config/testnet-hoodi.json @@ -0,0 +1,69 @@ +{ + "eigenLayer": { + "pausers": [ + "0x64D78399B0fa32EA72959f33edCF313159F3c13D" + ], + "unpauser": "0xE3328cb5068924119d6170496c4AB2dD12c12d15", + "rewardsUpdater": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", + "calculationIntervalSeconds": 86400, + "maxRewardsDuration": 6048000, + "maxRetroactiveLength": 7776000, + "maxFutureLength": 2592000, + "genesisRewardsTimestamp": 1710979200, + "activationDelay": 7200, + "globalCommissionBips": 1000, + "executorMultisig": "0xE3328cb5068924119d6170496c4AB2dD12c12d15", + "operationsMultisig": "0xE7f4E30D2619273468afe9EC0Acf805E55532257", + "minWithdrawalDelayBlocks": 50, + "delegationInitPausedStatus": 0, + "eigenPodManagerInitPausedStatus": 0, + "rewardsCoordinatorInitPausedStatus": 0, + "allocationManagerInitPausedStatus": 0, + "deallocationDelay": 50, + "allocationConfigurationDelay": 75, + "beaconChainGenesisTimestamp": 1710666600, + "delegationManager": "0x867837a9722C512e0862d8c2E15b8bE220E8b87d", + "strategyManager": "0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41", + "eigenPodManager": "0xcd1442415Fc5C29Aa848A49d2e232720BE07976c", + "avsDirectory": "0xD58f6844f79eB1fbd9f7091d05f7cb30d3363926", + "rewardsCoordinator": "0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7", + "allocationManager": "0x95a7431400F362F3647a69535C5666cA0133CAA0", + "permissionController": "0xdcCF401fD121d8C542E96BC1d0078884422aFAD2" + }, + "avs": { + "avsOwner": "0x0000000000000000000000000000000000000000", + "rewardsInitiator": "0x0000000000000000000000000000000000000000", + "validatorsStrategies": [ + "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0", + "0xf8a1a66130d614c7360e868576d5e59203475fe0", + "0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d" + ] + }, + "snowbridge": { + "randaoCommitDelay": 4, + "randaoCommitExpiration": 24, + "minNumRequiredSignatures": 5, + "startBlock": 1381173, + "rewardsMessageOrigin": "0xd0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215", + "initialValidatorSetId": 2303, + "initialValidatorHashes": [ + "0x0ec3102f334aba804c18b843e45ec874005587122a1b49273b1b04d6fd98b1a2", + "0xb277ac8a7aafc125d7da813a9b0fdae144922c165bfae194ebd94d6f3e4fe68e", + "0xcc6aefdce3f83d204893cb57388a72b4553b613f95b437ce548582470e62d1e7", + "0xcefa9940d25d21ac6d0a579727e8812283ed00d7ace9dfc9e30a0f95a0ea7bdd", + "0x8e720aed537cb30d204f1de9fb5aab6e0129acfc3f41a3c69259231c1f0f2685", + "0x5f883131cf6667cb8c2279caa182298e174bbca35c7c8c5679df6bad73be85cf", + "0x744ae85e99103a5ebcf9dd2fdcc18743012f0336f497fd3a05243a26a1a031b7" + ], + "nextValidatorSetId": 2304, + "nextValidatorHashes": [ + "0x0ec3102f334aba804c18b843e45ec874005587122a1b49273b1b04d6fd98b1a2", + "0xb277ac8a7aafc125d7da813a9b0fdae144922c165bfae194ebd94d6f3e4fe68e", + "0xcc6aefdce3f83d204893cb57388a72b4553b613f95b437ce548582470e62d1e7", + "0xcefa9940d25d21ac6d0a579727e8812283ed00d7ace9dfc9e30a0f95a0ea7bdd", + "0x8e720aed537cb30d204f1de9fb5aab6e0129acfc3f41a3c69259231c1f0f2685", + "0x5f883131cf6667cb8c2279caa182298e174bbca35c7c8c5679df6bad73be85cf", + "0x744ae85e99103a5ebcf9dd2fdcc18743012f0336f497fd3a05243a26a1a031b7" + ] + } +} diff --git a/contracts/deployments/stagenet-hoodi-rewards-info.json b/contracts/deployments/stagenet-hoodi-rewards-info.json new file mode 100644 index 00000000..32bba16a --- /dev/null +++ b/contracts/deployments/stagenet-hoodi-rewards-info.json @@ -0,0 +1 @@ +{"RewardsAgent": "0x2E039a88838241d1Ac738cf2e3C5763ba12571e7","RewardsAgentOrigin": "0x56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd"} \ No newline at end of file diff --git a/contracts/deployments/stagenet-hoodi.json b/contracts/deployments/stagenet-hoodi.json new file mode 100644 index 00000000..72b70a20 --- /dev/null +++ b/contracts/deployments/stagenet-hoodi.json @@ -0,0 +1 @@ +{"network": "stagenet-hoodi","BeefyClient": "0xE65dc4eCA2Fd428361076e1f204731224CeB4292","AgentExecutor": "0x35d3FdCB19A246a1763421168dF69dA3dE207063","Gateway": "0xE9352f1488F12bFEd722c133C129ca5F467463d1","ServiceManager": "0xED73cCaF067cebC706B2B3a6cf2b9af2c696c6d3","ServiceManagerImplementation": "0x5E1DA2eE025Dac2F8c391Ac86ebA20bd34c32465","RewardsAgent": "0x2E039a88838241d1Ac738cf2e3C5763ba12571e7","DelegationManager": "0x867837a9722C512e0862d8c2E15b8bE220E8b87d","StrategyManager": "0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41","AVSDirectory": "0xD58f6844f79eB1fbd9f7091d05f7cb30d3363926","RewardsCoordinator": "0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7","AllocationManager": "0x95a7431400F362F3647a69535C5666cA0133CAA0","PermissionController": "0xdcCF401fD121d8C542E96BC1d0078884422aFAD2"} \ No newline at end of file diff --git a/contracts/deployments/state-diff.checksum b/contracts/deployments/state-diff.checksum index 6bd67d4e..2384c13d 100644 --- a/contracts/deployments/state-diff.checksum +++ b/contracts/deployments/state-diff.checksum @@ -1 +1 @@ -711490494719593c219c35ca496cd28b86d9f54a \ No newline at end of file +9c861e3e1d290888127bc6d772fb1a3422bdf8b3 \ No newline at end of file diff --git a/contracts/deployments/state-diff.json b/contracts/deployments/state-diff.json index bf19287b..7b21fbfe 100644 --- a/contracts/deployments/state-diff.json +++ b/contracts/deployments/state-diff.json @@ -1,622 +1,71 @@ { - "33": { - "address": "0x9A676e781A523b5d0C0e43731313A708CB607508", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000a85233c63b9ee964add6f2cffe00fd84eb32338f", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65", - "0xedc9a600799bdec0e14ee5042ef794e1b4738abf52d225059d6b470373867218": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x0000000000000000000000000000000000000000000000000000000000000065": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x00000000000000000000000000000000000000000000000000000000000000cb": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc" - } - }, - "19": { - "address": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319", - "code": "0x608060405234801561000f575f5ffd5b5060043610610148575f3560e01c8063a1060c88116100bf578063dce974b911610079578063dce974b914610334578063df5cf7231461035b578063ec76f44214610382578063f2fde38b146103b5578063f698da25146103c8578063fabc1cbc146103d0575f5ffd5b8063a1060c881461029a578063a364f4da146102ad578063a98fb355146102c0578063c825fe68146102d3578063cd6dc687146102fa578063d79aceab1461030d575f5ffd5b80635ac86ab7116101105780635ac86ab7146101fa5780635c975abb1461021d578063715018a61461022f578063886f1195146102375780638da5cb5b146102765780639926ee7d14610287575f5ffd5b8063136439dd1461014c578063374823b51461016157806349075da3146101a357806354fd4d50146101dd578063595c6a67146101f2575b5f5ffd5b61015f61015a3660046110dc565b6103e3565b005b61018e61016f366004611107565b609960209081525f928352604080842090915290825290205460ff1681565b60405190151581526020015b60405180910390f35b6101d06101b1366004611131565b609860209081525f928352604080842090915290825290205460ff1681565b60405161019a919061117c565b6101e561041d565b60405161019a91906111d0565b61015f61044d565b61018e6102083660046111e9565b606654600160ff9092169190911b9081161490565b6066545b60405190815260200161019a565b61015f610461565b61025e7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6040516001600160a01b03909116815260200161019a565b6033546001600160a01b031661025e565b61015f610295366004611277565b610472565b6102216102a8366004611364565b610673565b61015f6102bb3660046113a7565b6106f2565b61015f6102ce3660046113c2565b6107b9565b6102217f809c5ac049c45b7a7f050a20f00c16cf63797efbf8b1eb8d749fdfa39ff8f92981565b61015f610308366004611107565b610800565b6102217fda2c89bafdd34776a2b8bb9c83c82f419e20cc8c67207f70edd58249b92661bd81565b6102217f4ee65f64218c67b68da66fd0db16560040a6b973290b9e71912d661ee53fe49581565b61025e7f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b61015f6103903660046110dc565b335f90815260996020908152604080832093835292905220805460ff19166001179055565b61015f6103c33660046113a7565b61091c565b610221610995565b61015f6103de3660046110dc565b610a4e565b6103eb610ab4565b60665481811681146104105760405163c61dca5d60e01b815260040160405180910390fd5b61041982610b57565b5050565b60606104487f76312e302e300000000000000000000000000000000000000000000000000006610b94565b905090565b610455610ab4565b61045f5f19610b57565b565b610469610bd1565b61045f5f610c2b565b5f61047c81610c7c565b6001335f9081526098602090815260408083206001600160a01b038816845290915290205460ff1660018111156104b5576104b5611168565b036104d357604051631aa528bb60e11b815260040160405180910390fd5b6001600160a01b0383165f90815260996020908152604080832085830151845290915290205460ff161561051a57604051630d4c4c9160e21b815260040160405180910390fd5b6040516336b87bd760e11b81526001600160a01b0384811660048301527f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821690636d70f7ae90602401602060405180830381865afa15801561057e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a29190611430565b6105bf57604051639f88c8af60e01b815260040160405180910390fd5b6105e3836105d7853386602001518760400151610673565b84516040860151610ca7565b6001600160a01b0383165f81815260996020908152604080832086830151845282528083208054600160ff19918216811790925533808652609885528386208787529094529382902080549094168117909355519092917ff0952b1c65271d819d39983d2abb044b9cace59bcc4d4dd389f586ebdcb15b4191610666919061117c565b60405180910390a3505050565b604080517fda2c89bafdd34776a2b8bb9c83c82f419e20cc8c67207f70edd58249b92661bd60208201526001600160a01b038087169282019290925290841660608201526080810183905260a081018290525f906106e99060c00160405160208183030381529060405280519060200120610cff565b95945050505050565b5f6106fc81610c7c565b6001335f9081526098602090815260408083206001600160a01b038716845290915290205460ff16600181111561073557610735611168565b14610753576040516352df45c960e01b815260040160405180910390fd5b335f8181526098602090815260408083206001600160a01b0387168085529252808320805460ff191690555190917ff0952b1c65271d819d39983d2abb044b9cace59bcc4d4dd389f586ebdcb15b41916107ad919061117c565b60405180910390a35050565b336001600160a01b03167fa89c1dc243d8908a96dd84944bcc97d6bc6ac00dd78e20621576be6a3c94371383836040516107f492919061144f565b60405180910390a25050565b5f54610100900460ff161580801561081e57505f54600160ff909116105b806108375750303b15801561083757505f5460ff166001145b61089f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff1916600117905580156108c0575f805461ff0019166101001790555b6108c982610b57565b6108d283610c2b565b8015610917575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b610924610bd1565b6001600160a01b0381166109895760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610896565b61099281610c2b565b50565b60408051808201909152600a81526922b4b3b2b72630bcb2b960b11b6020909101525f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea610a02610d45565b805160209182012060408051928301949094529281019190915260608101919091524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b610a56610dba565b60665480198219811614610a7d5760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016107f4565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa158015610b16573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a9190611430565b61045f57604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b60605f610ba083610e6b565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b6033546001600160a01b0316331461045f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610896565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606654600160ff83161b908116036109925760405163840a48d560e01b815260040160405180910390fd5b42811015610cc857604051630819bdcd60e01b815260040160405180910390fd5b610cdc6001600160a01b0385168484610e98565b610cf957604051638baa579f60e01b815260040160405180910390fd5b50505050565b5f610d08610995565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b60605f610d717f76312e302e300000000000000000000000000000000000000000000000000006610b94565b9050805f81518110610d8557610d8561147d565b016020908101516040516001600160f81b03199091169181019190915260210160405160208183030381529060405291505090565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e16573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3a9190611491565b6001600160a01b0316336001600160a01b03161461045f5760405163794821ff60e01b815260040160405180910390fd5b5f60ff8216601f811115610e9257604051632cd44ac360e21b815260040160405180910390fd5b92915050565b5f5f5f610ea58585610ef6565b90925090505f816004811115610ebd57610ebd611168565b148015610edb5750856001600160a01b0316826001600160a01b0316145b80610eec5750610eec868686610f38565b9695505050505050565b5f5f8251604103610f2a576020830151604084015160608501515f1a610f1e8782858561101f565b94509450505050610f31565b505f905060025b9250929050565b5f5f5f856001600160a01b0316631626ba7e60e01b8686604051602401610f609291906114ac565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610f9e91906114cc565b5f60405180830381855afa9150503d805f8114610fd6576040519150601f19603f3d011682016040523d82523d5f602084013e610fdb565b606091505b5091509150818015610fef57506020815110155b8015610eec57508051630b135d3f60e11b9061101490830160209081019084016114e2565b149695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561105457505f905060036110d3565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156110a5573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b0381166110cd575f600192509250506110d3565b91505f90505b94509492505050565b5f602082840312156110ec575f5ffd5b5035919050565b6001600160a01b0381168114610992575f5ffd5b5f5f60408385031215611118575f5ffd5b8235611123816110f3565b946020939093013593505050565b5f5f60408385031215611142575f5ffd5b823561114d816110f3565b9150602083013561115d816110f3565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b602081016002831061119c57634e487b7160e01b5f52602160045260245ffd5b91905290565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6111e260208301846111a2565b9392505050565b5f602082840312156111f9575f5ffd5b813560ff811681146111e2575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff8111828210171561124057611240611209565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561126f5761126f611209565b604052919050565b5f5f60408385031215611288575f5ffd5b8235611293816110f3565b9150602083013567ffffffffffffffff8111156112ae575f5ffd5b8301606081860312156112bf575f5ffd5b6112c761121d565b813567ffffffffffffffff8111156112dd575f5ffd5b8201601f810187136112ed575f5ffd5b803567ffffffffffffffff81111561130757611307611209565b61131a601f8201601f1916602001611246565b81815288602083850101111561132e575f5ffd5b816020840160208301375f6020928201830152835283810135908301525060409182013591810191909152919491935090915050565b5f5f5f5f60808587031215611377575f5ffd5b8435611382816110f3565b93506020850135611392816110f3565b93969395505050506040820135916060013590565b5f602082840312156113b7575f5ffd5b81356111e2816110f3565b5f5f602083850312156113d3575f5ffd5b823567ffffffffffffffff8111156113e9575f5ffd5b8301601f810185136113f9575f5ffd5b803567ffffffffffffffff81111561140f575f5ffd5b856020828401011115611420575f5ffd5b6020919091019590945092505050565b5f60208284031215611440575f5ffd5b815180151581146111e2575f5ffd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156114a1575f5ffd5b81516111e2816110f3565b828152604060208201525f6114c460408301846111a2565b949350505050565b5f82518060208501845e5f920191825250919050565b5f602082840312156114f2575f5ffd5b505191905056fea264697066735822122073ac1b7fd03357e63bd1ea96fdd2a71a85f098cadb19e9ccc9fc7028bc1c9a9664736f6c634300081c00330000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "38": { - "address": "0x59b670e9fA9D0A427751Af201D676719a970857b", - "code": "0x6080604052600436106101bd575f3560e01c80636691954e116100f2578063b522538a11610092578063d06d558711610062578063d06d55871461063f578063dda3346c1461065e578063ee94d67c1461067d578063f074ba621461069c575f5ffd5b8063b522538a146105ce578063c44e30dc146105ed578063c490744214610601578063c4d66de814610620575f5ffd5b80637439841f116100cd5780637439841f1461053457806374cdd7981461056957806388676cad1461059c5780639b4e4634146105bb575f5ffd5b80636691954e146104d65780636c0d2d5a146104e95780636fcd0e5314610508575f5ffd5b806342ecff2a1161015d57806352396a591161013857806352396a591461043657806354fd4d501461046a578063587533571461048b57806358eaee79146104aa575f5ffd5b806342ecff2a146102f25780634665bcda1461031857806347d283721461034b575f5ffd5b80632340e8d3116101985780632340e8d31461027a5780633474aa161461028f5780633f5fa57a146102c05780633f65cf19146102d3575f5ffd5b8063039157d2146101fb5780630b18ff661461021c5780631e51553314610258575f5ffd5b366101f7576040513481527f6fdd3dbdb173299608c0aa9f368735857c8842b581f8389238bf05bd04b3bf499060200160405180910390a1005b5f5ffd5b348015610206575f5ffd5b5061021a610215366004613a3e565b6106bb565b005b348015610227575f5ffd5b5060335461023b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610263575f5ffd5b5061026c6109f0565b60405190815260200161024f565b348015610285575f5ffd5b5061026c60395481565b34801561029a575f5ffd5b506034546001600160401b03165b6040516001600160401b03909116815260200161024f565b61021a6102ce366004613af9565b610a11565b3480156102de575f5ffd5b5061021a6102ed366004613b37565b610d49565b3480156102fd575f5ffd5b50603a546102a890600160401b90046001600160401b031681565b348015610323575f5ffd5b5061023b7f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b181565b348015610356575f5ffd5b506103db6040805160a0810182525f80825260208201819052918101829052606081018290526080810191909152506040805160a081018252603c548152603d5462ffffff811660208301526001600160401b0363010000008204811693830193909352600160581b810460070b6060830152600160981b9004909116608082015290565b60405161024f91905f60a0820190508251825262ffffff60208401511660208301526001600160401b036040840151166040830152606083015160070b60608301526001600160401b03608084015116608083015292915050565b348015610441575f5ffd5b506102a8610450366004613c0e565b603b6020525f90815260409020546001600160401b031681565b348015610475575f5ffd5b5061047e610fd2565b60405161024f9190613c57565b348015610496575f5ffd5b50603e5461023b906001600160a01b031681565b3480156104b5575f5ffd5b506104c96104c4366004613ca6565b610ffd565b60405161024f9190613d0c565b61021a6104e4366004613af9565b61105f565b3480156104f4575f5ffd5b5061026c610503366004613c0e565b611361565b348015610513575f5ffd5b50610527610522366004613d1a565b61146f565b60405161024f9190613d31565b34801561053f575f5ffd5b506104c961054e366004613d1a565b5f90815260366020526040902054600160c01b900460ff1690565b348015610574575f5ffd5b5061023b7f000000000000000000000000c7f2cf4845c6db0e1a1e91ed41bcd0fcc1b0e14181565b3480156105a7575f5ffd5b5061021a6105b6366004613d91565b61151a565b61021a6105c9366004613dac565b61160f565b3480156105d9575f5ffd5b506105276105e8366004613ca6565b61178d565b3480156105f8575f5ffd5b5061026c61187c565b34801561060c575f5ffd5b5061021a61061b366004613e41565b611898565b34801561062b575f5ffd5b5061021a61063a366004613e6b565b6119cf565b34801561064a575f5ffd5b5061021a610659366004613e6b565b611b19565b348015610669575f5ffd5b5061021a610678366004613f56565b611bad565b348015610688575f5ffd5b50603a546102a8906001600160401b031681565b3480156106a7575f5ffd5b5061021a6106b6366004614028565b611d0c565b604051635ac86ab760e01b8152600660048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa158015610721573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610745919061408f565b156107635760405163840a48d560e01b815260040160405180910390fd5b604051635ac86ab760e01b8152600860048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa1580156107c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ed919061408f565b1561080b5760405163840a48d560e01b815260040160405180910390fd5b5f61084f61081985806140aa565b808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525061210892505050565b5f818152603660209081526040808320815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b8104909416928101929092529394509192906060830190600160c01b900460ff1660028111156108bd576108bd613cd8565b60028111156108ce576108ce613cd8565b81525050905080604001516001600160401b0316876001600160401b03161161090a576040516337e07ffd60e01b815260040160405180910390fd5b60018160600151600281111561092257610922613cd8565b146109405760405163d49e19a760e01b815260040160405180910390fd5b61098361094d86806140aa565b808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525061212a92505050565b6109a05760405163161ce5ed60e31b815260040160405180910390fd5b6109b26109ac88611361565b87612152565b6109de6109be886121f7565b87356109ca88806140aa565b6109d760208b018b6140ef565b87516122ce565b6109e75f612402565b50505050505050565b5f610a0c71bbddc7ce488642fb579f8b00f3a590007251612582565b905090565b604051635ac86ab760e01b8152600a60048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa158015610a77573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9b919061408f565b15610ab95760405163840a48d560e01b815260040160405180910390fd5b6033546001600160a01b0316331480610adc5750603e546001600160a01b031633145b610af95760405163427a777960e01b815260040160405180910390fd5b5f610b0261187c565b90505f610b0f8483614145565b905080341015610b325760405163356680b760e01b815260040160405180910390fd5b5f610b3d823461415c565b90505f5b85811015610d305736878783818110610b5c57610b5c61416f565b9050602002810190610b6e9190614183565b90505f610bb7610b7e83806140ef565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260892505050565b90505f610bc483806140ef565b610bd46040860160208701613c0e565b604051602001610be6939291906141a1565b60405160208183030381529060405290505f710961ef480eb55e80d19ad83579a64c0070026001600160a01b03168883604051610c2391906141d9565b5f6040518083038185875af1925050503d805f8114610c5d576040519150601f19603f3d011682016040523d82523d5f602084013e610c62565b606091505b5050905080610c845760405163fc52d48360e01b815260040160405180910390fd5b610c946040850160208601613c0e565b6001600160401b03165f03610cd25760405183907f60d8ca014d4765a2b8b389e25714cb1cef83b574222911a01d90c1bd69d2d320905f90a2610d20565b827f8b2737bb64ab2f2dc09552dfa1c250399e6a42c7ea9f0e1c658f5d65d708ec05610d046040870160208801613c0e565b6040516001600160401b03909116815260200160405180910390a25b505060019092019150610b419050565b508015610d4157610d413382612699565b505050505050565b6033546001600160a01b0316331480610d6c5750603e546001600160a01b031633145b610d895760405163427a777960e01b815260040160405180910390fd5b604051635ac86ab760e01b8152600260048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa158015610def573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e13919061408f565b15610e315760405163840a48d560e01b815260040160405180910390fd5b8584148015610e3f57508382145b610e5c576040516343714afd60e01b815260040160405180910390fd5b603a546001600160401b03600160401b9091048116908a1611610e92576040516337e07ffd60e01b815260040160405180910390fd5b610ea4610e9e8a611361565b89612152565b5f805b87811015610f3d57610f298b8b358b8b85818110610ec757610ec761416f565b9050602002016020810190610edc91906141e4565b8a8a86818110610eee57610eee61416f565b9050602002810190610f0091906140ef565b8a8a88818110610f1257610f1261416f565b9050602002810190610f2491906140aa565b6127ae565b610f339083614208565b9150600101610ea7565b5060335460405163a1ca780b60e01b81526001600160a01b0391821660048201525f6024820152604481018390527f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b19091169063a1ca780b906064015f604051808303815f87803b158015610fb0575f5ffd5b505af1158015610fc2573d5f5f3e3d5ffd5b5050505050505050505050505050565b6060610a0c7f76312e302e300000000000000000000000000000000000000000000000000006612caf565b5f5f61103d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260892505050565b5f90815260366020526040902054600160c01b900460ff169150505b92915050565b604051635ac86ab760e01b8152600960048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa1580156110c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e9919061408f565b156111075760405163840a48d560e01b815260040160405180910390fd5b6033546001600160a01b031633148061112a5750603e546001600160a01b031633145b6111475760405163427a777960e01b815260040160405180910390fd5b5f6111506109f0565b90505f61115d8483614145565b9050803410156111805760405163356680b760e01b815260040160405180910390fd5b5f61118b823461415c565b90505f5b85811015610d3057368787838181106111aa576111aa61416f565b90506020028101906111bc9190614183565b90505f6111cc610b7e83806140ef565b90505f6111df610b7e60208501856140ef565b90505f6111eb8261146f565b905060018160600151600281111561120557611205613cd8565b146112235760405163d49e19a760e01b815260040160405180910390fd5b5f61122e85806140ef565b61123b60208801886140ef565b60405160200161124e949392919061421b565b60405160208183030381529060405290505f71bbddc7ce488642fb579f8b00f3a5900072516001600160a01b03168a8360405161128b91906141d9565b5f6040518083038185875af1925050503d805f81146112c5576040519150601f19603f3d011682016040523d82523d5f602084013e6112ca565b606091505b50509050806112ec5760405163fc52d48360e01b815260040160405180910390fd5b8385036113225760405185907fc97b965b92ae7fd20095fe8eb7b99f81f95f8c4adffb22a19116d8eb2846b016905f90a261134f565b604051849086907f42f9c9db2ca443e9ec62f4588bd0c9b241065c02c2a8001ac164ae1282dc7b94905f90a35b50506001909401935061118f92505050565b5f61136f611fff600c614145565b6113826001600160401b0384164261415c565b106113a057604051637944e66d60e11b815260040160405180910390fd5b604080516001600160401b03841660208201525f918291720f3df6d732807ef1319fb7b8bb8522d0beac02910160408051601f19818403018152908290526113e7916141d9565b5f60405180830381855afa9150503d805f811461141f576040519150601f19603f3d011682016040523d82523d5f602084013e611424565b606091505b509150915081801561143657505f8151115b6114535760405163558ad0a360e01b815260040160405180910390fd5b80806020019051810190611467919061423a565b949350505050565b611496604080516080810182525f8082526020820181905291810182905290606082015290565b5f82815260366020908152604091829020825160808101845281546001600160401b038082168352600160401b8204811694830194909452600160801b810490931693810193909352906060830190600160c01b900460ff16600281111561150057611500613cd8565b600281111561151157611511613cd8565b90525092915050565b6033546001600160a01b031633148061153d5750603e546001600160a01b031633145b61155a5760405163427a777960e01b815260040160405180910390fd5b604051635ac86ab760e01b8152600660048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa1580156115c0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e4919061408f565b156116025760405163840a48d560e01b815260040160405180910390fd5b61160b82612402565b5050565b336001600160a01b037f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b1161461165857604051633213a66160e21b815260040160405180910390fd5b346801bc16d674ec800000146116815760405163049696b360e31b815260040160405180910390fd5b7f000000000000000000000000c7f2cf4845c6db0e1a1e91ed41bcd0fcc1b0e1416001600160a01b031663228951186801bc16d674ec80000087876116c4612cec565b8888886040518863ffffffff1660e01b81526004016116e896959493929190614279565b5f604051808303818588803b1580156116ff575f5ffd5b505af1158015611711573d5f5f3e3d5ffd5b50505050507fa01003766d3cd97cf2ade5429690bf5d206be7fb01ef9d3a0089ecf67bc1121961177586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260892505050565b60405190815260200160405180910390a15050505050565b6117b4604080516080810182525f8082526020820181905291810182905290606082015290565b60365f6117f585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260892505050565b815260208082019290925260409081015f20815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b81049094169281019290925290916060830190600160c01b900460ff16600281111561186157611861613cd8565b600281111561187257611872613cd8565b9052509392505050565b5f610a0c710961ef480eb55e80d19ad83579a64c007002612582565b336001600160a01b037f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b116146118e157604051633213a66160e21b815260040160405180910390fd5b5f6118f0633b9aca00836142db565b9050611909633b9aca006001600160401b038316614145565b6034549092506001600160401b03908116908216111561193c576040516302c6f54760e21b815260040160405180910390fd5b603480548291905f906119599084906001600160401b03166142ee565b92506101000a8154816001600160401b0302191690836001600160401b03160217905550826001600160a01b03167f8947fd2ce07ef9cc302c4e8f0461015615d91ce851564839e91cc804c2f49d8e836040516119b891815260200190565b60405180910390a26119ca8383612699565b505050565b5f54610100900460ff16158080156119ed57505f54600160ff909116105b80611a065750303b158015611a0657505f5460ff166001145b611a6e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015611a8f575f805461ff0019166101001790555b6001600160a01b038216611ab6576040516339b190bb60e11b815260040160405180910390fd5b603380546001600160a01b0319166001600160a01b038416179055801561160b575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6033546001600160a01b03163314611b445760405163719f370360e11b815260040160405180910390fd5b603e54604080516001600160a01b03928316815291831660208301527ffb8129080a19d34dceac04ba253fc50304dc86c729bd63cdca4a969ad19a5eac910160405180910390a1603e80546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b03163314611bd85760405163719f370360e11b815260040160405180910390fd5b604051635ac86ab760e01b8152600560048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa158015611c3e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c62919061408f565b15611c805760405163840a48d560e01b815260040160405180910390fd5b8251845114611ca2576040516343714afd60e01b815260040160405180910390fd5b5f5b8451811015611d0557611cfd83858381518110611cc357611cc361416f565b6020026020010151878481518110611cdd57611cdd61416f565b60200260200101516001600160a01b0316612d1c9092919063ffffffff16565b600101611ca4565b5050505050565b604051635ac86ab760e01b8152600760048201819052907f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b031690635ac86ab790602401602060405180830381865afa158015611d72573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d96919061408f565b15611db45760405163840a48d560e01b815260040160405180910390fd5b603a54600160401b90046001600160401b03165f819003611de857604051631a544f4960e01b815260040160405180910390fd5b6040805160a081018252603c548152603d5462ffffff811660208301526001600160401b0363010000008204811693830193909352600160581b810460070b6060830152600160981b90049091166080820152611e4f611e47836121f7565b825188612d6e565b5f805b858110156120af5736878783818110611e6d57611e6d61416f565b9050602002810190611e7f919061430d565b80355f908152603660209081526040808320815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b8104909416928101929092529394509192906060830190600160c01b900460ff166002811115611eef57611eef613cd8565b6002811115611f0057611f00613cd8565b9052509050600181606001516002811115611f1d57611f1d613cd8565b14611f295750506120a7565b856001600160401b031681604001516001600160401b031610611f4d5750506120a7565b5f8080611f5d848a8f3588612e2f565b60208b0180519396509194509250611f7482614321565b62ffffff16905250608088018051849190611f9090839061433e565b6001600160401b0316905250606088018051839190611fb090839061435d565b60070b905250611fc0818861433e565b85355f908152603660209081526040918290208751815492890151938901516001600160401b03908116600160801b0267ffffffffffffffff60801b19958216600160401b026001600160801b0319909516919092161792909217928316821781556060880151939a50879390929091839160ff60c01b1990911668ffffffffffffffffff60801b1990911617600160c01b83600281111561206457612064613cd8565b021790555050604051863591506001600160401b038b16907fe4866335761a51dcaff766448ab0af6064291ee5dc94e68492bb9cd757c1e350905f90a350505050505b600101611e52565b506001600160401b038084165f908152603b60205260408120805484939192916120db9185911661433e565b92506101000a8154816001600160401b0302191690836001600160401b031602179055506109e782612f45565b5f815f8151811061211b5761211b61416f565b60200260200101519050919050565b5f8160038151811061213e5761213e61416f565b60200260200101515f5f1b14159050919050565b61215e60036020614145565b61216b60208301836140ef565b90501461218b576040516313717da960e21b815260040160405180910390fd5b6121da61219b60208301836140ef565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525086925050843590506003613165565b61160b576040516309bde33960e01b815260040160405180910390fd5b5f5f7f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b16001600160a01b0316632704351a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612255573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612279919061438c565b9050806001600160401b03165f036122a4576040516341a02cc960e01b815260040160405180910390fd5b806001600160401b0316836001600160401b031611156122c55760016122c7565b5f5b9392505050565b600884146122ef5760405163200591bd60e01b815260040160405180910390fd5b5f6122f98861319a565b90508061230860286001614208565b6123129190614208565b61231d906020614145565b831461233c576040516313717da960e21b815260040160405180910390fd5b5f6123788787808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506131c292505050565b90505f64ffffffffff841661238f60286001614208565b600b901b1790506123d986868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508d9250869150859050613165565b6123f6576040516309bde33960e01b815260040160405180910390fd5b50505050505050505050565b603a54600160401b90046001600160401b0316156124325760405162be9bc360e81b815260040160405180910390fd5b603a546001600160401b03428116911603612460576040516367db5b8b60e01b815260040160405180910390fd5b6034545f906001600160401b031661247c633b9aca00476142db565b61248691906142ee565b905081801561249c57506001600160401b038116155b156124ba576040516332dea95960e21b815260040160405180910390fd5b5f6040518060a001604052806124cf42611361565b815260395462ffffff1660208201526001600160401b0380851660408301525f60608301819052608090920191909152603a805442909216600160401b026fffffffffffffffff000000000000000019909216919091179055905061253381612f45565b805160208083015160405162ffffff90911681526001600160401b034216917f575796133bbed337e5b39aa49a30dc2556a91e0c6c2af4b7b886ae77ebef1076910160405180910390a3505050565b5f5f5f836001600160a01b03166040515f60405180830381855afa9150503d805f81146125ca576040519150601f19603f3d011682016040523d82523d5f602084013e6125cf565b606091505b50915091508180156125e2575080516020145b6125ff5760405163c90158af60e01b815260040160405180910390fd5b611467816143a7565b5f815160301461262b57604051634f88323960e11b815260040160405180910390fd5b6040516002906126419084905f906020016143ca565b60408051601f198184030181529082905261265b916141d9565b602060405180830381855afa158015612676573d5f5f3e3d5ffd5b5050506040513d601f19601f82011682018060405250810190611059919061423a565b804710156126e95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611a65565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612732576040519150601f19603f3d011682016040523d82523d5f602084013e612737565b606091505b50509050806119ca5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611a65565b5f5f6127eb8484808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525061210892505050565b5f818152603660209081526040808320815160808101835281546001600160401b038082168352600160401b8204811695830195909552600160801b8104909416928101929092529394509192906060830190600160c01b900460ff16600281111561285957612859613cd8565b600281111561286a5761286a613cd8565b90525090505f8160600151600281111561288657612886613cd8565b146128a4576040516335e09e9d60e01b815260040160405180910390fd5b6001600160401b0380166128e98686808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525061349092505050565b6001600160401b03160361291057604051631958236d60e21b815260040160405180910390fd5b6001600160401b0380166129558686808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506134b492505050565b6001600160401b03161461297c57604051632eade63760e01b815260040160405180910390fd5b612984612cec565b61298d906143a7565b6129c88686808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506134cb92505050565b1480612a1d57506129d76134df565b6129e0906143a7565b612a1b8686808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506134cb92505050565b145b612a3a57604051633772dd5360e11b815260040160405180910390fd5b5f612a768686808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506134fb92505050565b9050612a8f612a848c6121f7565b8b88888c8c8f6122ce565b60398054905f612a9e836143ee565b9091555050603a545f90600160401b90046001600160401b031615612ad557603a54600160401b90046001600160401b0316612ae2565b603a546001600160401b03165b6040805160808101825264ffffffffff8d1681526001600160401b03858116602083015283169181019190915290915060608101600190525f858152603660209081526040918290208351815492850151938501516001600160401b03908116600160801b0267ffffffffffffffff60801b19958216600160401b026001600160801b031990951691909216179290921792831682178155606084015190929091839160ff60c01b1990911668ffffffffffffffffff60801b1990911617600160c01b836002811115612bb757612bb7613cd8565b021790555050603d8054849250601390612be2908490600160981b90046001600160401b031661433e565b92506101000a8154816001600160401b0302191690836001600160401b031602179055507f101790c2993f6a4d962bd17c786126823ba1c4cf04ff4cccb2659d50fb20aee884604051612c3791815260200190565b60405180910390a1604080518581526001600160401b03838116602083015284168183015290517fcdae700d7241bc027168c53cf6f889763b0a2c88a65d77fc13a8a9fef0d8605f9181900360600190a1612c9f633b9aca006001600160401b038416614145565b9c9b505050505050505050505050565b60605f612cbb83613512565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b604051606090612d0890600160f81b905f903090602001614406565b604051602081830303815290604052905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526119ca908490613539565b5f612d788461319a565b9050612d85816003614208565b612d90906020614145565b612d9d60208401846140ef565b905014612dbd576040516313717da960e21b815260040160405180910390fd5b6003811b600c17612e12612dd460208501856140ef565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250889250508635905084613165565b611d05576040516309bde33960e01b815260040160405180910390fd5b5f5f5f866020015192505f612e4886895f01518761360c565b9050836001600160401b0316816001600160401b031614612ebc57612e6d8482614444565b60408051873581526001600160401b038a8116602083015284168183015290519194507fcdae700d7241bc027168c53cf6f889763b0a2c88a65d77fc13a8a9fef0d8605f919081900360600190a15b6001600160401b0380821660208a0181905290881660408a01525f03612f3a5760398054905f612eeb83614473565b909155505060026060890152612f0083614488565b6040519092508535906001600160401b038916907f5ce0aa04ae51d52da6e680fbe0336d2e2432f7c3dc2d4f3193204c57b9072107905f90a35b509450945094915050565b8051603c556020810151603d805460408401516060850151608086015162ffffff9095166affffffffffffffffffffff19909316831763010000006001600160401b0393841602176fffffffffffffffffffffffffffffffff60581b1916600160581b9183169190910267ffffffffffffffff60981b191617600160981b919094160292909217905515612fd65750565b60808101516034545f91612ff2916001600160401b031661433e565b90505f82606001518360400151613009919061435d565b60408401516034805492935090915f9061302d9084906001600160401b031661433e565b82546101009290920a6001600160401b03818102199093169183160217909155603a8054600160401b810483166001600160801b03199091161790555f915061307d90633b9aca00908516614145565b90505f613092633b9aca00600785900b6144ad565b603a546040518281529192506001600160401b0316907f525408c201bc1576eb44116f6478f1c2a54775b19a043bcfdc708364f74f8e449060200160405180910390a260335460405163a1ca780b60e01b81526001600160a01b03918216600482015260248101849052604481018390527f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b19091169063a1ca780b906064015f604051808303815f87803b158015613148575f5ffd5b505af115801561315a573d5f5f3e3d5ffd5b505050505050505050565b5f83613184576040516329e7276760e11b815260040160405180910390fd5b836131908685856136ea565b1495945050505050565b5f808260018111156131ae576131ae613cd8565b146131ba576006611059565b600592915050565b5f60018251116131e55760405163f8ef036760e01b815260040160405180910390fd5b6131ef82516137dd565b61320c5760405163f6558f5160e01b815260040160405180910390fd5b5f6002835161321b91906142db565b90505f816001600160401b0381111561323657613236613e86565b60405190808252806020026020018201604052801561325f578160200160208202803683370190505b5090505f5b82811015613359576002856132798383614145565b815181106132895761328961416f565b60200260200101518683600261329f9190614145565b6132aa906001614208565b815181106132ba576132ba61416f565b60200260200101516040516020016132dc929190918252602082015260400190565b60408051601f19818403018152908290526132f6916141d9565b602060405180830381855afa158015613311573d5f5f3e3d5ffd5b5050506040513d601f19601f82011682018060405250810190613334919061423a565b8282815181106133465761334661416f565b6020908102919091010152600101613264565b505b8160011461346d5761336e6002836142db565b91505f5b82811015613467576002826133878383614145565b815181106133975761339761416f565b6020026020010151838360026133ad9190614145565b6133b8906001614208565b815181106133c8576133c861416f565b60200260200101516040516020016133ea929190918252602082015260400190565b60408051601f1981840301815290829052613404916141d9565b602060405180830381855afa15801561341f573d5f5f3e3d5ffd5b5050506040513d601f19601f82011682018060405250810190613442919061423a565b8282815181106134545761345461416f565b6020908102919091010152600101613372565b5061335b565b805f8151811061347f5761347f61416f565b602002602001015192505050919050565b5f611059826005815181106134a7576134a761416f565b60200260200101516137fc565b5f611059826006815181106134a7576134a761416f565b5f8160018151811061211b5761211b61416f565b604051606090612d0890600160f91b905f903090602001614406565b5f611059826002815181106134a7576134a761416f565b5f60ff8216601f81111561105957604051632cd44ac360e21b815260040160405180910390fd5b5f61358d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166138639092919063ffffffff16565b905080515f14806135ad5750808060200190518101906135ad919061408f565b6119ca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611a65565b5f61361960266001614208565b613624906020614145565b61363160408401846140ef565b905014613651576040516313717da960e21b815260040160405180910390fd5b5f61365d6004856144dc565b64ffffffffff1690506136b661367660408501856140ef565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508992505050602086013584613165565b6136d3576040516309bde33960e01b815260040160405180910390fd5b6136e1836020013585613871565b95945050505050565b5f83515f141580156137075750602084516137059190614505565b155b613724576040516313717da960e21b815260040160405180910390fd5b604080516020808201909252848152905b855181116137b457613748600285614505565b5f0361377a5781515f528086015160205260208260405f60026107d05a03fa61376f575f5ffd5b6002840493506137a2565b808601515f52815160205260208260405f60026107d05a03fa61379b575f5ffd5b6002840493505b6137ad602082614208565b9050613735565b5082156137d4576040516363df817160e01b815260040160405180910390fd5b51949350505050565b5f811580159061105957506137f360018361415c565b82161592915050565b60f881901c60e882901c61ff00161760d882901c62ff0000161760c882901c63ff000000161764ff0000000060b883901c161765ff000000000060a883901c161766ff000000000000609883901c161767ff0000000000000060889290921c919091161790565b606061146784845f8561389d565b5f8061387e600484614518565b613889906040614541565b64ffffffffff16905061146784821b6137fc565b6060824710156138fe5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611a65565b5f5f866001600160a01b0316858760405161391991906141d9565b5f6040518083038185875af1925050503d805f8114613953576040519150601f19603f3d011682016040523d82523d5f602084013e613958565b606091505b509150915061396987838387613974565b979650505050505050565b606083156139e25782515f036139db576001600160a01b0385163b6139db5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a65565b5081611467565b61146783838151156139f75781518083602001fd5b8060405162461bcd60e51b8152600401611a659190613c57565b6001600160401b0381168114613a25575f5ffd5b50565b5f60408284031215613a38575f5ffd5b50919050565b5f5f5f60608486031215613a50575f5ffd5b8335613a5b81613a11565b925060208401356001600160401b03811115613a75575f5ffd5b613a8186828701613a28565b92505060408401356001600160401b03811115613a9c575f5ffd5b613aa886828701613a28565b9150509250925092565b5f5f83601f840112613ac2575f5ffd5b5081356001600160401b03811115613ad8575f5ffd5b6020830191508360208260051b8501011115613af2575f5ffd5b9250929050565b5f5f60208385031215613b0a575f5ffd5b82356001600160401b03811115613b1f575f5ffd5b613b2b85828601613ab2565b90969095509350505050565b5f5f5f5f5f5f5f5f60a0898b031215613b4e575f5ffd5b8835613b5981613a11565b975060208901356001600160401b03811115613b73575f5ffd5b613b7f8b828c01613a28565b97505060408901356001600160401b03811115613b9a575f5ffd5b613ba68b828c01613ab2565b90975095505060608901356001600160401b03811115613bc4575f5ffd5b613bd08b828c01613ab2565b90955093505060808901356001600160401b03811115613bee575f5ffd5b613bfa8b828c01613ab2565b999c989b5096995094979396929594505050565b5f60208284031215613c1e575f5ffd5b81356122c781613a11565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6122c76020830184613c29565b5f5f83601f840112613c79575f5ffd5b5081356001600160401b03811115613c8f575f5ffd5b602083019150836020828501011115613af2575f5ffd5b5f5f60208385031215613cb7575f5ffd5b82356001600160401b03811115613ccc575f5ffd5b613b2b85828601613c69565b634e487b7160e01b5f52602160045260245ffd5b60038110613d0857634e487b7160e01b5f52602160045260245ffd5b9052565b602081016110598284613cec565b5f60208284031215613d2a575f5ffd5b5035919050565b5f6080820190506001600160401b0383511682526001600160401b0360208401511660208301526001600160401b0360408401511660408301526060830151613d7d6060840182613cec565b5092915050565b8015158114613a25575f5ffd5b5f60208284031215613da1575f5ffd5b81356122c781613d84565b5f5f5f5f5f60608688031215613dc0575f5ffd5b85356001600160401b03811115613dd5575f5ffd5b613de188828901613c69565b90965094505060208601356001600160401b03811115613dff575f5ffd5b613e0b88828901613c69565b96999598509660400135949350505050565b6001600160a01b0381168114613a25575f5ffd5b8035613e3c81613e1d565b919050565b5f5f60408385031215613e52575f5ffd5b8235613e5d81613e1d565b946020939093013593505050565b5f60208284031215613e7b575f5ffd5b81356122c781613e1d565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715613ec257613ec2613e86565b604052919050565b5f6001600160401b03821115613ee257613ee2613e86565b5060051b60200190565b5f82601f830112613efb575f5ffd5b8135613f0e613f0982613eca565b613e9a565b8082825260208201915060208360051b860101925085831115613f2f575f5ffd5b602085015b83811015613f4c578035835260209283019201613f34565b5095945050505050565b5f5f5f60608486031215613f68575f5ffd5b83356001600160401b03811115613f7d575f5ffd5b8401601f81018613613f8d575f5ffd5b8035613f9b613f0982613eca565b8082825260208201915060208360051b850101925088831115613fbc575f5ffd5b6020840193505b82841015613fe7578335613fd681613e1d565b825260209384019390910190613fc3565b955050505060208401356001600160401b03811115614004575f5ffd5b61401086828701613eec565b92505061401f60408501613e31565b90509250925092565b5f5f5f6040848603121561403a575f5ffd5b83356001600160401b0381111561404f575f5ffd5b61405b86828701613a28565b93505060208401356001600160401b03811115614076575f5ffd5b61408286828701613ab2565b9497909650939450505050565b5f6020828403121561409f575f5ffd5b81516122c781613d84565b5f5f8335601e198436030181126140bf575f5ffd5b8301803591506001600160401b038211156140d8575f5ffd5b6020019150600581901b3603821315613af2575f5ffd5b5f5f8335601e19843603018112614104575f5ffd5b8301803591506001600160401b0382111561411d575f5ffd5b602001915036819003821315613af2575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761105957611059614131565b8181038181111561105957611059614131565b634e487b7160e01b5f52603260045260245ffd5b5f8235603e19833603018112614197575f5ffd5b9190910192915050565b8284823760c09190911b6001600160c01b0319169101908152600801919050565b5f81518060208401855e5f93019283525090919050565b5f6122c782846141c2565b5f602082840312156141f4575f5ffd5b813564ffffffffff811681146122c7575f5ffd5b8082018082111561105957611059614131565b838582375f8482015f8152838582375f93019283525090949350505050565b5f6020828403121561424a575f5ffd5b5051919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b608081525f61428c60808301888a614251565b828103602084015261429e8188613c29565b905082810360408401526142b3818688614251565b915050826060830152979650505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f826142e9576142e96142c7565b500490565b6001600160401b03828116828216039081111561105957611059614131565b5f8235605e19833603018112614197575f5ffd5b5f62ffffff82168061433557614335614131565b5f190192915050565b6001600160401b03818116838216019081111561105957611059614131565b600781810b9083900b01677fffffffffffffff8113677fffffffffffffff198212171561105957611059614131565b5f6020828403121561439c575f5ffd5b81516122c781613a11565b80516020808301519190811015613a38575f1960209190910360031b1b16919050565b5f6143d582856141c2565b6001600160801b03199390931683525050601001919050565b5f600182016143ff576143ff614131565b5060010190565b6001600160f81b03199390931683526001600160a81b031991909116600183015260601b6bffffffffffffffffffffffff1916600c82015260200190565b600782810b9082900b03677fffffffffffffff198112677fffffffffffffff8213171561105957611059614131565b5f8161448157614481614131565b505f190190565b5f8160070b677fffffffffffffff1981036144a5576144a5614131565b5f0392915050565b8082025f8212600160ff1b841416156144c8576144c8614131565b818105831482151761105957611059614131565b5f64ffffffffff8316806144f2576144f26142c7565b8064ffffffffff84160491505092915050565b5f82614513576145136142c7565b500690565b5f64ffffffffff83168061452e5761452e6142c7565b8064ffffffffff84160691505092915050565b64ffffffffff8181168382160290811690818114613d7d57613d7d61413156fea2646970667358221220d7f03c11afe2f1c649534ba5e4f99bc743e129e34f9d832c789daea8e1e84efe64736f6c634300081c00330000000000000000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "26": { - "address": "0x0B306BF915C4d645ff596e518fAf3F9669b97016", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000004a679253410272dd5232b3ff7cf5dbb88f295319", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "4": { - "address": "0x1111111111111111111111111111111111111111", - "code": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80632baeceb71461004e5780638381f58a146100585780638da5cb5b14610073578063d826f88f1461009e575b5f5ffd5b6100566100a6565b005b6100605f5481565b6040519081526020015b60405180910390f35b600154610086906001600160a01b031681565b6040516001600160a01b03909116815260200161006a565b61005661010d565b5f5f54116100fb5760405162461bcd60e51b815260206004820152601f60248201527f4e756d6265722073686f756c642062652067726561746572207468616e20300060448201526064015b60405180910390fd5b60015f54610109919061016d565b5f55565b6001546001600160a01b031633146101675760405162461bcd60e51b815260206004820152601760248201527f4f6e6c792063616c6c61626c65206279206f776e65722100000000000000000060448201526064016100f2565b600a5f55565b8181038181111561018c57634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220ac5899491afd834afd223fd632497d1c0c7593961eda22f04c58db4b504999cf64736f6c634300081c0033000000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000a" - } - }, - "36": { - "address": "0xdf077F5F72071dF6e8B0a78071E496bA17b5Ee0c", - "code": "0x608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f8168881565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b7981565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c00330000000000", - "storage": {} - }, - "24": { - "address": "0x0000BBdDc7CE488642fb579F8B00f3a590007251", - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd00", - "storage": {} - }, - "41": { - "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", - "code": "0x73dc64a140aa3e981100a9beca4e685f962f0cf6c93014608060405260043610610090575f3560e01c8063741fad8811610063578063741fad88146101125780638257f3d514610131578063ae8a4d9814610150578063c31308d11461016f575f5ffd5b80630c86ea461461009457806325394645146100b55780635b2e9c4c146100d457806365529675146100f3575b5f5ffd5b81801561009f575f5ffd5b506100b36100ae366004610a3a565b61018e565b005b8180156100c0575f5ffd5b506100b36100cf366004610a3a565b610229565b8180156100df575f5ffd5b506100b36100ee366004610a3a565b6102af565b8180156100fe575f5ffd5b506100b361010d366004610a8f565b610337565b81801561011d575f5ffd5b506100b361012c366004610adf565b6103aa565b81801561013c575f5ffd5b506100b361014b366004610a3a565b610433565b81801561015b575f5ffd5b506100b361016a366004610a3a565b6104c4565b81801561017a575f5ffd5b506100b3610189366004610a8f565b6104ee565b7f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f65f6101bc84840185610baf565b8051835560208101516001840180546fffffffffffffffffffffffffffffffff19166001600160801b039092169190911790556040808201516002850155519091507f5e3c25378b5946068b94aa2ea10c4c1e215cc975f994322b159ddc9237a973d4905f90a150505050565b5f61023682840184610c6d565b80516020820151604080840151905163a3499c7360e01b8152939450732279b7a0a67db372996a5fab50d91eaa73d2ebe69363a3499c739361027e9390929091600401610d22565b5f6040518083038186803b158015610294575f5ffd5b505af41580156102a6573d5f5f3e3d5ffd5b50505050505050565b7f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e5f6102dd84840185610d51565b805160208201516001600160801b03908116600160801b0291161760028401556040808201516003850155519091507f4793c0cb5bef4b1fdbbfbcf17e06991844eb881088b012442af17a12ff38d5cd905f90a150505050565b5f61034482840184610d86565b90505f610353825f01516105c4565b60208301519091506001600160a01b031661038a576103858582846040015185606001516001600160801b031661061c565b6103a3565b6103a38582846020015185604001518660600151610679565b5050505050565b60408051637061726160e01b602080830191909152607d60e31b602483015282516008818403018152602890920190925280519101206103eb9084906106de565b15610408576040516282b42960e81b815260040160405180910390fd5b5f61041582840184610de4565b905061042d815f0151826020015183604001516106e9565b50505050565b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab5f61046084840185610e2f565b8051835491925090839060ff19166001838181111561048157610481610e7d565b021790555080516040517f4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a916104b691610e91565b60405180910390a150505050565b5f6104d182840184610eb7565b905061042d815f0151826020015183604001518460600151610762565b5f6104fb82840184610f71565b90505f61050a825f01516105c4565b90508160200151515f03610531576040516309e256f760e21b815260040160405180910390fd5b5f5f836020015180602001905181019061054b919061104f565b90925090505f82801561056057610560610e7d565b036102a6575f5f5f8380602001905181019061057c919061109f565b919450925090506001600160a01b0383166105ab576105a68a8784846001600160801b031661061c565b6105b8565b6105b88a87858585610679565b50505050505050505050565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b0316806106175760405163d3227c9b60e01b815260040160405180910390fd5b919050565b6040516001600160a01b0383166024820152604481018290525f9060640160408051601f198184030181529190526020810180516001600160e01b03166305b1137b60e01b17905290506106718486836108ad565b505050505050565b6040516001600160a01b038085166024830152831660448201526001600160801b03821660648201525f9060840160408051601f198184030181529190526020810180516001600160e01b03166309733b7b60e21b17905290506102a68587836108ad565b818114155b92915050565b5f6106f384610939565b6040516340c10f1960e01b81526001600160a01b0385811660048301526001600160801b0385166024830152919250908216906340c10f19906044015f604051808303815f87803b158015610746575f5ffd5b505af1158015610758573d5f5f3e3d5ffd5b5050505050505050565b5f8481527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b0316156107d857604051633ea7ffd960e11b815260040160405180910390fd5b5f8585856040516107e8906109e9565b6107f4939291906110e9565b604051809103905ff08015801561080d573d5f5f3e3d5ffd5b50604080518082018252600180825260208083018c81525f8d815260048901835285812080546001600160a01b0319166001600160a01b038916908117909155808252898452908690208551815460ff19169015151781559151919093015592519081529293509189917f57f58171b8777633d03aff1e7408b96a3d910c93a7ce433a8cb7fb837dc306a6910160405180910390a2509695505050505050565b60605f5f856001600160a01b0316639bb66b2886866040518363ffffffff1660e01b81526004016108df929190611121565b5f604051808303815f875af11580156108fa573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610921919081019061114c565b9150915061092f82826109ca565b9695505050505050565b5f8181527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b03166109ae5760405163259ba1ad60e01b815260040160405180910390fd5b5f9283526004016020525060409020546001600160a01b031690565b606082156109d95750806106e3565b8151156100905781518083602001fd5b610c358061116d83390190565b5f5f83601f840112610a06575f5ffd5b5081356001600160401b03811115610a1c575f5ffd5b602083019150836020828501011115610a33575f5ffd5b9250929050565b5f5f60208385031215610a4b575f5ffd5b82356001600160401b03811115610a60575f5ffd5b610a6c858286016109f6565b90969095509350505050565b6001600160a01b0381168114610a8c575f5ffd5b50565b5f5f5f60408486031215610aa1575f5ffd5b8335610aac81610a78565b925060208401356001600160401b03811115610ac6575f5ffd5b610ad2868287016109f6565b9497909650939450505050565b5f5f5f60408486031215610af1575f5ffd5b8335925060208401356001600160401b03811115610ac6575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715610b4357610b43610b0d565b60405290565b604051608081016001600160401b0381118282101715610b4357610b43610b0d565b604051601f8201601f191681016001600160401b0381118282101715610b9357610b93610b0d565b604052919050565b6001600160801b0381168114610a8c575f5ffd5b5f6060828403128015610bc0575f5ffd5b50610bc9610b21565b823581526020830135610bdb81610b9b565b60208201526040928301359281019290925250919050565b5f6001600160401b03821115610c0b57610c0b610b0d565b50601f01601f191660200190565b5f82601f830112610c28575f5ffd5b8135602083015f610c40610c3b84610bf3565b610b6b565b9050828152858383011115610c53575f5ffd5b828260208301375f92810160200192909252509392505050565b5f60208284031215610c7d575f5ffd5b81356001600160401b03811115610c92575f5ffd5b820160608185031215610ca3575f5ffd5b610cab610b21565b8135610cb681610a78565b81526020828101359082015260408201356001600160401b03811115610cda575f5ffd5b610ce686828501610c19565b604083015250949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60018060a01b0384168152826020820152606060408201525f610d486060830184610cf4565b95945050505050565b5f6060828403128015610d62575f5ffd5b50610d6b610b21565b8235610d7681610b9b565b81526020830135610bdb81610b9b565b5f6080828403128015610d97575f5ffd5b50610da0610b49565b823581526020830135610db281610a78565b60208201526040830135610dc581610a78565b60408201526060830135610dd881610b9b565b60608201529392505050565b5f6060828403128015610df5575f5ffd5b50610dfe610b21565b823581526020830135610e1081610a78565b60208201526040830135610e2381610b9b565b60408201529392505050565b5f6020828403128015610e40575f5ffd5b50604051602081016001600160401b0381118282101715610e6357610e63610b0d565b604052823560028110610e74575f5ffd5b81529392505050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610eb157634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610ec7575f5ffd5b81356001600160401b03811115610edc575f5ffd5b820160808185031215610eed575f5ffd5b610ef5610b49565b8135815260208201356001600160401b03811115610f11575f5ffd5b610f1d86828501610c19565b60208301525060408201356001600160401b03811115610f3b575f5ffd5b610f4786828501610c19565b6040830152506060820135915060ff82168214610f62575f5ffd5b60608101919091529392505050565b5f60208284031215610f81575f5ffd5b81356001600160401b03811115610f96575f5ffd5b820160408185031215610fa7575f5ffd5b604080519081016001600160401b0381118282101715610fc957610fc9610b0d565b6040528135815260208201356001600160401b03811115610fe8575f5ffd5b610ff486828501610c19565b602083015250949350505050565b5f82601f830112611011575f5ffd5b815161101f610c3b82610bf3565b818152846020838601011115611033575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f60408385031215611060575f5ffd5b82516001811061106e575f5ffd5b60208401519092506001600160401b03811115611089575f5ffd5b61109585828601611002565b9150509250929050565b5f5f5f606084860312156110b1575f5ffd5b83516110bc81610a78565b60208501519093506110cd81610a78565b60408501519092506110de81610b9b565b809150509250925092565b606081525f6110fb6060830186610cf4565b828103602084015261110d8186610cf4565b91505060ff83166040830152949350505050565b6001600160a01b03831681526040602082018190525f9061114490830184610cf4565b949350505050565b5f5f6040838503121561115d575f5ffd5b8251801515811461106e575f5ffdfe60c060405234801561000f575f5ffd5b50604051610c35380380610c3583398101604081905261002e916100f5565b5f61003984826101f6565b50600161004683826101f6565b5060ff1660a0525050336080526102b0565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011261007b575f5ffd5b81516001600160401b0381111561009457610094610058565b604051601f8201601f19908116603f011681016001600160401b03811182821017156100c2576100c2610058565b6040528181528382016020018510156100d9575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f60608486031215610107575f5ffd5b83516001600160401b0381111561011c575f5ffd5b6101288682870161006c565b602086015190945090506001600160401b03811115610145575f5ffd5b6101518682870161006c565b925050604084015160ff81168114610167575f5ffd5b809150509250925092565b600181811c9082168061018657607f821691505b6020821081036101a457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156101f157805f5260205f20601f840160051c810160208510156101cf5750805b601f840160051c820191505b818110156101ee575f81556001016101db565b50505b505050565b81516001600160401b0381111561020f5761020f610058565b6102238161021d8454610172565b846101aa565b6020601f821160018114610255575f831561023e5750848201515b5f19600385901b1c1916600184901b1784556101ee565b5f84815260208120601f198516915b828110156102845787850151825560209485019460019092019101610264565b50848210156102a157868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60805160a0516109566102df5f395f61019e01525f818161013a015281816104f301526105c201526109565ff3fe608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c806340c10f19116100935780639dc29fac116100635780639dc29fac14610247578063a9059cbb1461025a578063d505accf1461026d578063dd62ed3e14610280575f5ffd5b806340c10f19146101da57806370a08231146101ef5780637ecebe001461021757806395d89b411461023f575f5ffd5b806318160ddd116100ce57806318160ddd1461017457806323b872dd14610186578063313ce567146101995780633644e515146101d2575f5ffd5b806306fdde03146100f4578063095ea7b314610112578063116191b614610135575b5f5ffd5b6100fc6102b8565b6040516101099190610749565b60405180910390f35b610125610120366004610799565b610343565b6040519015158152602001610109565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610109565b6005545b604051908152602001610109565b6101256101943660046107c1565b6103d5565b6101c07f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610109565b61017861046f565b6101ed6101e8366004610799565b6104e8565b005b6101786101fd3660046107fb565b6001600160a01b03165f9081526002602052604090205490565b6101786102253660046107fb565b6001600160a01b03165f9081526004602052604090205490565b6100fc6105aa565b6101ed610255366004610799565b6105b7565b610125610268366004610799565b61064d565b6101ed61027b366004610814565b61069d565b61017861028e366004610881565b6001600160a01b039182165f90815260036020908152604080832093909416825291909152205490565b5f80546102c4906108b2565b80601f01602080910402602001604051908101604052809291908181526020018280546102f0906108b2565b801561033b5780601f106103125761010080835404028352916020019161033b565b820191905f5260205f20905b81548152906001019060200180831161031e57829003601f168201915b505050505081565b6040516338412ce560e01b8152600260048201526001600160a01b0383166024820152604481018290525f9073a513e6e4b8f2a923d98304ec87f64353c4d5c853906338412ce5906064015b602060405180830381865af41580156103aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ce91906108ea565b9392505050565b6040516301b8d43b60e41b8152600260048201526001600160a01b03808516602483015283166044820152606481018290525f9073a513e6e4b8f2a923d98304ec87f64353c4d5c85390631b8d43b090608401602060405180830381865af4158015610443573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061046791906108ea565b949350505050565b6040516312af95d360e31b81525f600482018190529073a513e6e4b8f2a923d98304ec87f64353c4d5c8539063957cae9890602401602060405180830381865af41580156104bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e39190610909565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610530576040516282b42960e81b815260040160405180910390fd5b60405163480ff06560e01b8152600260048201526001600160a01b03831660248201526044810182905273a513e6e4b8f2a923d98304ec87f64353c4d5c8539063480ff065906064015b5f6040518083038186803b158015610590575f5ffd5b505af41580156105a2573d5f5f3e3d5ffd5b505050505050565b600180546102c4906108b2565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105ff576040516282b42960e81b815260040160405180910390fd5b60405163c7f6238760e01b8152600260048201526001600160a01b03831660248201526044810182905273a513e6e4b8f2a923d98304ec87f64353c4d5c8539063c7f623879060640161057a565b60405163379bc60360e11b8152600260048201526001600160a01b0383166024820152604481018290525f9073a513e6e4b8f2a923d98304ec87f64353c4d5c85390636f378c069060640161038f565b604051630334f36960e31b8152600260048201525f60248201526001600160a01b038089166044830152871660648201526084810186905260a4810185905260ff841660c482015260e48101839052610104810182905273a513e6e4b8f2a923d98304ec87f64353c4d5c853906319a79b4890610124015f6040518083038186803b15801561072a575f5ffd5b505af415801561073c573d5f5f3e3d5ffd5b5050505050505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610794575f5ffd5b919050565b5f5f604083850312156107aa575f5ffd5b6107b38361077e565b946020939093013593505050565b5f5f5f606084860312156107d3575f5ffd5b6107dc8461077e565b92506107ea6020850161077e565b929592945050506040919091013590565b5f6020828403121561080b575f5ffd5b6103ce8261077e565b5f5f5f5f5f5f5f60e0888a03121561082a575f5ffd5b6108338861077e565b96506108416020890161077e565b95506040880135945060608801359350608088013560ff81168114610864575f5ffd5b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215610892575f5ffd5b61089b8361077e565b91506108a96020840161077e565b90509250929050565b600181811c908216806108c657607f821691505b6020821081036108e457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156108fa575f5ffd5b815180151581146103ce575f5ffd5b5f60208284031215610919575f5ffd5b505191905056fea2646970667358221220e1f5b5d05dc7259c2004ce8b2365485a31341d166e578c6bed74cf416d43d0b864736f6c634300081c0033a2646970667358221220993e175405432033ed7aea33210be529d0ba9c2edc6085e7b95533cc13f90a0064736f6c634300081c003300", - "storage": {} - }, - "17": { - "address": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f", - "code": "0x608060405234801561000f575f5ffd5b506004361061026b575f3560e01c80637ecebe001161014b578063ca8aa7c7116100bf578063f2fde38b11610084578063f2fde38b1461062f578063f3b4a00014610642578063f698da251461064c578063fabc1cbc14610654578063fd98042314610667578063fe243a171461067a575f5ffd5b8063ca8aa7c71461059b578063cbc2bd62146105c2578063de44acb6146105d5578063df5cf723146105f5578063e7a050aa1461061c575f5ffd5b80638da5cb5b116101105780638da5cb5b1461052b57806394f649dd1461053c578063967fc0d21461054f5780639ac01d6114610562578063b5d8b5b814610575578063c665670214610588575f5ffd5b80637ecebe001461047f578063829fca731461049e578063886f1195146104b157806388c10299146104f05780638b8aac3c14610503575f5ffd5b806350ff7225116101e25780635de08ff2116101a75780635de08ff2146103fc578063663c1de41461040f578063715018a614610431578063724af4231461043957806376fb162b1461044c5780637def15641461045f575f5ffd5b806350ff72251461037c57806354fd4d50146103a4578063595c6a67146103b95780635ac86ab7146103c15780635c975abb146103f4575f5ffd5b806332e89ace1161023357806332e89ace146102f157806336a8c500146103045780633f292b081461031a5780633fb99ca51461032f57806348825e94146103425780634b6d5d6e14610369575f5ffd5b8063136439dd1461026f5780631794bb3c146102845780632d44def6146102975780632eae418c146102bd57806331f8fb4c146102d0575b5f5ffd5b61028261027d366004612e33565b6106a4565b005b610282610292366004612e5e565b6106de565b6102aa6102a5366004612eb2565b610804565b6040519081526020015b60405180910390f35b6102826102cb366004612ef0565b6108b6565b6102e36102de366004612f3e565b610982565b6040516102b4929190612fda565b6102aa6102ff36600461304b565b610b10565b61030c610b95565b6040516102b4929190613125565b610322610cb0565b6040516102b4919061317b565b61028261033d3660046131d8565b610d98565b6102aa7f4337f82d142e41f2a8c10547cd8c859bddb92262a61058e77842e24d9dea922481565b61028261037736600461321c565b610ee0565b61038f61038a366004612e5e565b61102d565b604080519283526020830191909152016102b4565b6103ac6110a1565b6040516102b49190613265565b6102826110d1565b6103e46103cf366004613277565b609854600160ff9092169190911b9081161490565b60405190151581526020016102b4565b6098546102aa565b61028261040a366004613297565b6110e5565b6103e461041d36600461321c565b60d16020525f908152604090205460ff1681565b610282611238565b6102aa610447366004612e5e565b611249565b6102aa61045a366004612eb2565b6112a6565b61047261046d366004613306565b6112f5565b6040516102b49190613320565b6102aa61048d36600461321c565b60ca6020525f908152604090205481565b6102aa6104ac366004612f3e565b611327565b6104d87f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6040516001600160a01b0390911681526020016102b4565b6104726104fe366004612f3e565b611361565b6102aa61051136600461321c565b6001600160a01b03165f90815260ce602052604090205490565b6033546001600160a01b03166104d8565b6102e361054a36600461321c565b611498565b60cb546104d8906001600160a01b031681565b6102aa610570366004613332565b61160f565b610282610583366004613297565b6116a0565b61028261059636600461321c565b6117e7565b6104d87f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed81565b6104d86105d0366004613393565b61180a565b6105e86105e336600461321c565b61183e565b6040516102b491906133bd565b6104d87f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b6102aa61062a366004612e5e565b6118b1565b61028261063d36600461321c565b6118e4565b6104d8620e16e481565b6102aa61195a565b610282610662366004612e33565b611a13565b6102aa61067536600461321c565b611a80565b6102aa6106883660046133cf565b60cd60209081525f928352604080842090915290825290205481565b6106ac611a95565b60985481811681146106d15760405163c61dca5d60e01b815260040160405180910390fd5b6106da82611b38565b5050565b5f54610100900460ff16158080156106fc57505f54600160ff909116105b806107155750303b15801561071557505f5460ff166001145b61077d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff19166001179055801561079e575f805461ff0019166101001790555b6107a782611b38565b6107b084611b75565b6107b983611bc6565b80156107fe575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b5f61080d611c2f565b6108a38484847f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b0316630f3df50e896040518263ffffffff1660e01b815260040161085f919061344f565b602060405180830381865afa15801561087a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061089e919061345d565b611c88565b90506108af6001606555565b9392505050565b336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8216146108ff5760405163f739589b60e01b815260040160405180910390fd5b610907611c2f565b604051636ce5768960e11b81526001600160a01b0384169063d9caed129061093790879086908690600401613478565b6020604051808303815f875af1158015610953573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610977919061349c565b506107fe6001606555565b6060805f60d7816109a061099b368990038901896134b3565b611e90565b81526020019081526020015f205f8581526020019081526020015f2090505f6109c882611ef3565b90505f81516001600160401b038111156109e4576109e4613007565b604051908082528060200260200182016040528015610a0d578160200160208202803683370190505b5090505f82516001600160401b03811115610a2a57610a2a613007565b604051908082528060200260200182016040528015610a53578160200160208202803683370190505b5090505f5b8351811015610b0057838181518110610a7357610a7361350f565b6020026020010151838281518110610a8d57610a8d61350f565b60200260200101906001600160a01b031690816001600160a01b031681525050610ad9848281518110610ac257610ac261350f565b602002602001015186611eff90919063ffffffff16565b9050828281518110610aed57610aed61350f565b6020908102919091010152600101610a58565b50909450925050505b9250929050565b5f5f610b1b81611f23565b610b23611c2f565b6001600160a01b0385165f90815260ca6020526040902054610b5486610b4d818c8c8c878c61160f565b8688611f4e565b6001600160a01b0386165f90815260ca60205260409020600182019055610b7d868a8a8a611fa0565b925050610b8a6001606555565b509695505050505050565b6060805f610ba360d461210d565b90505f816001600160401b03811115610bbe57610bbe613007565b604051908082528060200260200182016040528015610be7578160200160208202803683370190505b5090505f826001600160401b03811115610c0357610c03613007565b604051908082528060200260200182016040528015610c2c578160200160208202803683370190505b5090505f5b83811015610ca5575f5f610c4660d484612117565b9150915081858481518110610c5d57610c5d61350f565b60200260200101906001600160a01b031690816001600160a01b03168152505080848481518110610c9057610c9061350f565b60209081029190910101525050600101610c31565b509094909350915050565b60605f610cbd60d8612125565b90505f816001600160401b03811115610cd857610cd8613007565b604051908082528060200260200182016040528015610d1c57816020015b604080518082019091525f8082526020820152815260200190600190039081610cf65790505b5090505f5b82811015610d9157610d6c610d3760d88361212e565b604080518082019091525f80825260208201525060408051808201909152606082901c815263ffffffff909116602082015290565b828281518110610d7e57610d7e61350f565b6020908102919091010152600101610d21565b5092915050565b336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821614610de15760405163f739589b60e01b815260040160405180910390fd5b610de9611c2f565b5f60d781610dff61099b368990038901896134b3565b815260208082019290925260409081015f90812087825290925290209050610e28818484612139565b610e455760405163ca354fa360e01b815260040160405180910390fd5b610e62610e5a61099b368890038801886134b3565b60d89061214e565b50610e978460da5f610e7c61099b368b90038b018b6134b3565b81526020019081526020015f2061214e90919063ffffffff16565b507f5f5209798bbac45a16d2dc3bc67319fab26ee00153916d6f07b69f8a134a1e8b85858585604051610ecd9493929190613523565b60405180910390a1506107fe6001606555565b610ee8611c2f565b5f610ef460d483611eff565b915050610f0260d483612159565b50604080516001600160a01b0384168152602081018390527fd9d082c3ec4f3a3ffa55c324939a06407f5fbcb87d5e0ce3b9508c92c84ed839910160405180910390a1801561101f57816001600160a01b031663d9caed12620e16e4846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fbe919061345d565b846040518463ffffffff1660e01b8152600401610fdd93929190613478565b6020604051808303815f875af1158015610ff9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101d919061349c565b505b5061102a6001606555565b50565b5f80336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8216146110785760405163f739589b60e01b815260040160405180910390fd5b611080611c2f565b61108b85858561216d565b915091506110996001606555565b935093915050565b60606110cc7f76312e302e3000000000000000000000000000000000000000000000000000066122d5565b905090565b6110d9611a95565b6110e35f19611b38565b565b60cb546001600160a01b03163314611110576040516320ba3ff960e21b815260040160405180910390fd5b611118611c2f565b805f5b8181101561122c5760d15f8585848181106111385761113861350f565b905060200201602081019061114d919061321c565b6001600160a01b0316815260208101919091526040015f205460ff1661122457600160d15f8686858181106111845761118461350f565b9050602002016020810190611199919061321c565b6001600160a01b0316815260208101919091526040015f20805460ff19169115159190911790557f0c35b17d91c96eb2751cd456e1252f42a386e524ef9ff26ecc9950859fdc04fe8484838181106111f3576111f361350f565b9050602002016020810190611208919061321c565b6040516001600160a01b03909116815260200160405180910390a15b60010161111b565b50506106da6001606555565b611240612312565b6110e35f611b75565b5f336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8216146112935760405163f739589b60e01b815260040160405180910390fd5b61129b611c2f565b6108a384848461236c565b5f806112eb8360d7836112c161099b368b90038b018b6134b3565b81526020019081526020015f205f8781526020019081526020015f20611eff90919063ffffffff16565b9695505050505050565b606061132160da5f61130f61099b368790038701876134b3565b81526020019081526020015f2061241a565b92915050565b5f6108af60d78261134061099b368890038801886134b3565b81526020019081526020015f205f8481526020019081526020015f2061210d565b606061136b611c2f565b5f6113a560d78261138461099b368990038901896134b3565b81526020019081526020015f205f8581526020019081526020015f20611ef3565b80519091505f816001600160401b038111156113c3576113c3613007565b6040519080825280602002602001820160405280156113ec578160200160208202803683370190505b5090505f5b828110156114895761146487878684815181106114105761141061350f565b60200260200101517f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b0316630f3df50e8c6040518263ffffffff1660e01b815260040161085f919061344f565b8282815181106114765761147661350f565b60209081029190910101526001016113f1565b50925050506113216001606555565b6001600160a01b0381165f90815260ce6020526040812054606091829190816001600160401b038111156114ce576114ce613007565b6040519080825280602002602001820160405280156114f7578160200160208202803683370190505b5090505f5b82811015611585576001600160a01b0386165f90815260cd6020908152604080832060ce909252822080549192918490811061153a5761153a61350f565b5f9182526020808320909101546001600160a01b0316835282019290925260400190205482518390839081106115725761157261350f565b60209081029190910101526001016114fc565b5060ce5f866001600160a01b03166001600160a01b031681526020019081526020015f2081818054806020026020016040519081016040528092919081815260200182805480156115fd57602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116115df575b50505050509150935093505050915091565b604080517f4337f82d142e41f2a8c10547cd8c859bddb92262a61058e77842e24d9dea922460208201526001600160a01b03808916928201929092528187166060820152908516608082015260a0810184905260c0810183905260e081018290525f90611695906101000160405160208183030381529060405280519060200120612426565b979650505050505050565b60cb546001600160a01b031633146116cb576040516320ba3ff960e21b815260040160405180910390fd5b6116d3611c2f565b805f5b8181101561122c5760d15f8585848181106116f3576116f361350f565b9050602002016020810190611708919061321c565b6001600160a01b0316815260208101919091526040015f205460ff16156117df575f60d15f86868581811061173f5761173f61350f565b9050602002016020810190611754919061321c565b6001600160a01b0316815260208101919091526040015f20805460ff19169115159190911790557f4074413b4b443e4e58019f2855a8765113358c7c72e39509c6af45fc0f5ba0308484838181106117ae576117ae61350f565b90506020020160208101906117c3919061321c565b6040516001600160a01b03909116815260200160405180910390a15b6001016116d6565b6117ef612312565b6117f7611c2f565b61180081611bc6565b61102a6001606555565b60ce602052815f5260405f208181548110611823575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0381165f90815260ce60209081526040918290208054835181840281018401909452808452606093928301828280156118a557602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611887575b50505050509050919050565b5f5f6118bc81611f23565b6118c4611c2f565b6118d033868686611fa0565b91506118dc6001606555565b509392505050565b6118ec612312565b6001600160a01b0381166119515760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610774565b61102a81611b75565b60408051808201909152600a81526922b4b3b2b72630bcb2b960b11b6020909101525f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea6119c761246c565b805160209182012060408051928301949094529281019190915260608101919091524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b611a1b6124e1565b60985480198219811614611a425760405163c61dca5d60e01b815260040160405180910390fd5b609882905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b5f5f611a8d60d484611eff565b949350505050565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa158015611af7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b1b9190613555565b6110e357604051631d77d47760e21b815260040160405180910390fd5b609881905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60cb54604080516001600160a01b03928316815291831660208301527f4264275e593955ff9d6146a51a4525f6ddace2e81db9391abcc9d1ca48047d29910160405180910390a160cb80546001600160a01b0319166001600160a01b0392909216919091179055565b600260655403611c815760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610774565b6002606555565b5f8060d781611c9f61099b368a90038a018a6134b3565b815260208082019290925260409081015f90812088825290925281209150611cc78286611eff565b9150611cd590508286612159565b505f8115611dec57856001600160a01b031663d9caed1286886001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d29573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d4d919061345d565b856040518463ffffffff1660e01b8152600401611d6c93929190613478565b6020604051808303815f875af1158015611d88573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dac919061349c565b90507fe6413aa0c789e437b0a06bf64b20926584f066c79a2d8b80a759c85472f7b0af88888885604051611de39493929190613523565b60405180910390a15b5f611df684611ef3565b519050805f03611e8457611e348860da5f611e1961099b368f90038f018f6134b3565b81526020019081526020015f2061259290919063ffffffff16565b50611e5f60da5f611e4d61099b368e90038e018e6134b3565b81526020019081526020015f20612125565b5f03611e8457611e82611e7a61099b368c90038c018c6134b3565b60d890612592565b505b50979650505050505050565b5f815f0151826020015163ffffffff16604051602001611edb92919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b60405160208183030381529060405261132190613574565b60605f6108af8361259d565b5f808080611f16866001600160a01b0387166125a8565b9097909650945050505050565b609854600160ff83161b9081160361102a5760405163840a48d560e01b815260040160405180910390fd5b42811015611f6f57604051630819bdcd60e01b815260040160405180910390fd5b611f836001600160a01b03851684846125e0565b6107fe57604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b0383165f90815260d16020526040812054849060ff16611fda57604051632efd965160e11b815260040160405180910390fd5b611fef6001600160a01b038516338786612634565b6040516311f9fbc960e21b81526001600160a01b038581166004830152602482018590528616906347e7ef24906044016020604051808303815f875af115801561203b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205f919061349c565b91505f5f61206e88888661216d565b604051631e328e7960e11b81526001600160a01b038b811660048301528a8116602483015260448201849052606482018390529294509092507f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8290911690633c651cf2906084015f604051808303815f87803b1580156120ec575f5ffd5b505af11580156120fe573d5f5f3e3d5ffd5b50505050505050949350505050565b5f6113218261268c565b5f808080611f168686612696565b5f611321825490565b5f6108af83836126bf565b5f611a8d846001600160a01b038516846126e5565b5f6108af8383612701565b5f6108af836001600160a01b03841661274d565b5f806001600160a01b038516612196576040516316f2ccc960e01b815260040160405180910390fd5b825f036121b6576040516342061b2560e11b815260040160405180910390fd5b6001600160a01b038086165f90815260cd602090815260408083209388168352929052908120549081900361225c576001600160a01b0386165f90815260ce60209081526040909120541061221e576040516301a1443960e31b815260040160405180910390fd5b6001600160a01b038681165f90815260ce602090815260408220805460018101825590835291200180546001600160a01b0319169187169190911790555b61226684826135ab565b6001600160a01b038088165f90815260cd60209081526040808320938a16835292905281902091909155517f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62906122c290889088908890613478565b60405180910390a1959294509192505050565b60605f6122e183612769565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b6033546001600160a01b031633146110e35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610774565b5f815f0361238d576040516342061b2560e11b815260040160405180910390fd5b6001600160a01b038085165f90815260cd6020908152604080832093871683529290522054808311156123d357604051634b18b19360e01b815260040160405180910390fd5b6123dd83826135be565b6001600160a01b038087165f90815260cd602090815260408083209389168352929052908120829055909150819003611a8d57611a8d8585612790565b60605f6108af8361290e565b5f61242f61195a565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b60605f6124987f76312e302e3000000000000000000000000000000000000000000000000000066122d5565b9050805f815181106124ac576124ac61350f565b016020908101516040516001600160f81b03199091169181019190915260210160405160208183030381529060405291505090565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561253d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612561919061345d565b6001600160a01b0316336001600160a01b0316146110e35760405163794821ff60e01b815260040160405180910390fd5b5f6108af8383612966565b60606113218261241a565b5f8181526002830160205260408120548190806125d5576125c98585612a49565b92505f9150610b099050565b600192509050610b09565b5f5f5f6125ed8585612a54565b90925090505f816004811115612605576126056135d1565b1480156126235750856001600160a01b0316826001600160a01b0316145b806112eb57506112eb868686612a93565b6107fe846323b872dd60e01b85858560405160240161265593929190613478565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612b7a565b5f61132182612125565b5f80806126a3858561212e565b5f81815260029690960160205260409095205494959350505050565b5f825f0182815481106126d4576126d461350f565b905f5260205f200154905092915050565b5f8281526002840160205260408120829055611a8d848461214e565b5f81815260018301602052604081205461274657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155611321565b505f611321565b5f81815260028301602052604081208190556108af8383612592565b5f60ff8216601f81111561132157604051632cd44ac360e21b815260040160405180910390fd5b6001600160a01b0382165f90815260ce6020526040812054905b818110156128a2576001600160a01b038481165f90815260ce60205260409020805491851691839081106127e0576127e061350f565b5f918252602090912001546001600160a01b03160361289a576001600160a01b0384165f90815260ce60205260409020805461281e906001906135be565b8154811061282e5761282e61350f565b5f9182526020808320909101546001600160a01b03878116845260ce909252604090922080549190921691908390811061286a5761286a61350f565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506128a2565b6001016127aa565b8181036128c257604051632df15a4160e11b815260040160405180910390fd5b6001600160a01b0384165f90815260ce602052604090208054806128e8576128e86135e5565b5f8281526020902081015f1990810180546001600160a01b031916905501905550505050565b6060815f018054806020026020016040519081016040528092919081815260200182805480156118a557602002820191905f5260205f20905b8154815260200190600101908083116129475750505050509050919050565b5f8181526001830160205260408120548015612a40575f6129886001836135be565b85549091505f9061299b906001906135be565b90508181146129fa575f865f0182815481106129b9576129b961350f565b905f5260205f200154905080875f0184815481106129d9576129d961350f565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080612a0b57612a0b6135e5565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611321565b5f915050611321565b5f6108af8383612c52565b5f5f8251604103612a88576020830151604084015160608501515f1a612a7c87828585612c69565b94509450505050610b09565b505f90506002610b09565b5f5f5f856001600160a01b0316631626ba7e60e01b8686604051602401612abb9291906135f9565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612af99190613611565b5f60405180830381855afa9150503d805f8114612b31576040519150601f19603f3d011682016040523d82523d5f602084013e612b36565b606091505b5091509150818015612b4a57506020815110155b80156112eb57508051630b135d3f60e11b90612b6f908301602090810190840161349c565b149695505050505050565b5f612bce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d269092919063ffffffff16565b905080515f1480612bee575080806020019051810190612bee9190613555565b612c4d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610774565b505050565b5f81815260018301602052604081205415156108af565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612c9e57505f90506003612d1d565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612cef573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116612d17575f60019250925050612d1d565b91505f90505b94509492505050565b6060611a8d84845f85855f5f866001600160a01b03168587604051612d4b9190613611565b5f6040518083038185875af1925050503d805f8114612d85576040519150601f19603f3d011682016040523d82523d5f602084013e612d8a565b606091505b50915091506116958783838760608315612e045782515f03612dfd576001600160a01b0385163b612dfd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610774565b5081611a8d565b611a8d8383815115612e195781518083602001fd5b8060405162461bcd60e51b81526004016107749190613265565b5f60208284031215612e43575f5ffd5b5035919050565b6001600160a01b038116811461102a575f5ffd5b5f5f5f60608486031215612e70575f5ffd5b8335612e7b81612e4a565b92506020840135612e8b81612e4a565b929592945050506040919091013590565b5f60408284031215612eac575f5ffd5b50919050565b5f5f5f60808486031215612ec4575f5ffd5b612ece8585612e9c565b9250604084013591506060840135612ee581612e4a565b809150509250925092565b5f5f5f5f60808587031215612f03575f5ffd5b8435612f0e81612e4a565b93506020850135612f1e81612e4a565b92506040850135612f2e81612e4a565b9396929550929360600135925050565b5f5f60608385031215612f4f575f5ffd5b612f598484612e9c565b946040939093013593505050565b5f8151808452602084019350602083015f5b82811015612fa05781516001600160a01b0316865260209586019590910190600101612f79565b5093949350505050565b5f8151808452602084019350602083015f5b82811015612fa0578151865260209586019590910190600101612fbc565b604081525f612fec6040830185612f67565b8281036020840152612ffe8185612faa565b95945050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561304357613043613007565b604052919050565b5f5f5f5f5f5f60c08789031215613060575f5ffd5b863561306b81612e4a565b9550602087013561307b81612e4a565b945060408701359350606087013561309281612e4a565b92506080870135915060a08701356001600160401b038111156130b3575f5ffd5b8701601f810189136130c3575f5ffd5b80356001600160401b038111156130dc576130dc613007565b6130ef601f8201601f191660200161301b565b8181528a6020838501011115613103575f5ffd5b816020840160208301375f602083830101528093505050509295509295509295565b604080825283519082018190525f9060208501906060840190835b818110156131675783516001600160a01b0316835260209384019390920191600101613140565b505083810360208501526112eb8186612faa565b602080825282518282018190525f918401906040840190835b818110156131cd57835180516001600160a01b0316845260209081015163ffffffff168185015290930192604090920191600101613194565b509095945050505050565b5f5f5f5f60a085870312156131eb575f5ffd5b6131f58686612e9c565b935060408501359250606085013561320c81612e4a565b9396929550929360800135925050565b5f6020828403121561322c575f5ffd5b81356108af81612e4a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6108af6020830184613237565b5f60208284031215613287575f5ffd5b813560ff811681146108af575f5ffd5b5f5f602083850312156132a8575f5ffd5b82356001600160401b038111156132bd575f5ffd5b8301601f810185136132cd575f5ffd5b80356001600160401b038111156132e2575f5ffd5b8560208260051b84010111156132f6575f5ffd5b6020919091019590945092505050565b5f60408284031215613316575f5ffd5b6108af8383612e9c565b602081525f6108af6020830184612faa565b5f5f5f5f5f5f60c08789031215613347575f5ffd5b863561335281612e4a565b9550602087013561336281612e4a565b9450604087013561337281612e4a565b959894975094956060810135955060808101359460a0909101359350915050565b5f5f604083850312156133a4575f5ffd5b82356133af81612e4a565b946020939093013593505050565b602081525f6108af6020830184612f67565b5f5f604083850312156133e0575f5ffd5b82356133eb81612e4a565b915060208301356133fb81612e4a565b809150509250929050565b803563ffffffff81168114613419575f5ffd5b919050565b803561342981612e4a565b6001600160a01b0316825263ffffffff61344560208301613406565b1660208301525050565b60408101611321828461341e565b5f6020828403121561346d575f5ffd5b81516108af81612e4a565b6001600160a01b039384168152919092166020820152604081019190915260600190565b5f602082840312156134ac575f5ffd5b5051919050565b5f60408284031280156134c4575f5ffd5b50604080519081016001600160401b03811182821017156134e7576134e7613007565b60405282356134f581612e4a565b815261350360208401613406565b60208201529392505050565b634e487b7160e01b5f52603260045260245ffd5b60a08101613531828761341e565b60408201949094526001600160a01b03929092166060830152608090910152919050565b5f60208284031215613565575f5ffd5b815180151581146108af575f5ffd5b80516020808301519190811015612eac575f1960209190910360031b1b16919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561132157611321613597565b8181038181111561132157611321613597565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b828152604060208201525f611a8d6040830184613237565b5f82518060208501845e5f92019182525091905056fea26469706673582212204cd82bcd16986fe6b441e4b7c389c7f12dd596c825079086d78383b1e3d02f8364736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "27": { - "address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "28": { - "address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000067d269191c92caf3cd7723f116c85e6e9bf55933", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788" - } - }, - "39": { - "address": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44", - "code": "0x608060405234801561000f575f5ffd5b50600436106102b1575f3560e01c80636d70f7ae1161017b578063bb45fef2116100e4578063e4cc3f901161009e578063f698da2511610079578063f698da25146107ce578063fabc1cbc146107d6578063fd8aa88d146107e9578063fe4b84df146107fc575f5ffd5b8063e4cc3f9014610788578063eea9064b1461079b578063f0e0e676146107ae575f5ffd5b8063bb45fef2146106b9578063bfae3fd2146106e6578063c448feb8146106f9578063c978f7ac1461072d578063ca8aa7c71461074e578063da8be86414610775575f5ffd5b80639104c319116101355780639104c319146106175780639435bb431461063257806399f5371b14610645578063a178848414610665578063a33a343314610684578063b7f06ebe14610697575f5ffd5b80636d70f7ae1461057a5780636e1744481461058d578063778e55f3146105a057806378296ec5146105ca578063886f1195146105dd5780639004134714610604575f5ffd5b806354b7c96c1161021d5780635c975abb116101d75780635c975abb146104d45780635d975e88146104dc5780635dd68579146104fd57806360a0d1ce1461051e57806365da12641461053157806366d5ba9314610559575f5ffd5b806354b7c96c1461045b57806354fd4d501461046e578063595c6a6714610483578063597b36da1461048b5780635ac86ab71461049e5780635ae679a7146104c1575f5ffd5b806339b70e381161026e57806339b70e381461036a5780633c651cf2146103a95780633cdeb5e0146103bc5780633e28391d146103ea5780634657e26a1461040d5780634665bcda14610434575f5ffd5b806304a4f979146102b55780630b9f487a146102ef5780630dd8dd0214610302578063136439dd1461032257806325df922e146103375780632aa6d88814610357575b5f5ffd5b6102dc7f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad81565b6040519081526020015b60405180910390f35b6102dc6102fd366004614a7f565b61080f565b610315610310366004614b16565b610897565b6040516102e69190614b54565b610335610330366004614b8b565b610b09565b005b61034a610345366004614d20565b610b43565b6040516102e69190614dce565b610335610365366004614e30565b610ca3565b6103917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b6040516001600160a01b0390911681526020016102e6565b6103356103b7366004614e8e565b610df7565b6103916103ca366004614ed1565b6001600160a01b039081165f908152609960205260409020600101541690565b6103fd6103f8366004614ed1565b610f4a565b60405190151581526020016102e6565b6103917f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c81565b6103917f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b181565b610335610469366004614eec565b610f69565b610476610fd7565b6040516102e69190614f51565b610335611007565b6102dc61049936600461501f565b61101b565b6103fd6104ac366004615050565b606654600160ff9092169190911b9081161490565b6102dc6104cf366004615084565b61104a565b6066546102dc565b6104ef6104ea366004614b8b565b6111bc565b6040516102e69291906151b9565b61051061050b366004614ed1565b6111d9565b6040516102e692919061522b565b61033561052c366004615298565b611303565b61039161053f366004614ed1565b609a6020525f90815260409020546001600160a01b031681565b61056c610567366004614ed1565b6114ae565b6040516102e69291906152d7565b6103fd610588366004614ed1565b6117ae565b6102dc61059b366004614eec565b6117e6565b6102dc6105ae366004614eec565b609860209081525f928352604080842090915290825290205481565b6103356105d83660046152e9565b611890565b6103917f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b61034a610612366004615339565b611926565b61039173beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b610335610640366004615385565b6119fc565b610658610653366004614b8b565b611ab7565b6040516102e69190615421565b6102dc610673366004614ed1565b609f6020525f908152604090205481565b610315610692366004615433565b611bd3565b6103fd6106a5366004614b8b565b609e6020525f908152604090205460ff1681565b6103fd6106c736600461551a565b609c60209081525f928352604080842090915290825290205460ff1681565b6102dc6106f4366004614eec565b611beb565b60405163ffffffff7f00000000000000000000000000000000000000000000000000000000000000321681526020016102e6565b61074061073b366004615339565b611c27565b6040516102e6929190615544565b6103917f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed81565b610315610783366004614ed1565b611eb4565b610335610796366004615563565b611fdd565b6103356107a9366004615433565b612015565b6107c16107bc3660046155e1565b612080565b6040516102e6919061568e565b6102dc612125565b6103356107e4366004614b8b565b6121de565b6103156107f7366004614ed1565b61224c565b61033561080a366004614b8b565b61226f565b604080517f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad60208201526001600160a01b03808616928201929092528187166060820152908516608082015260a0810183905260c081018290525f9061088d9060e00160405160208183030381529060405280519060200120612380565b9695505050505050565b606060016108a4816123ae565b6108ac6123dc565b5f836001600160401b038111156108c5576108c5614ba2565b6040519080825280602002602001820160405280156108ee578160200160208202803683370190505b50335f908152609a60205260408120549192506001600160a01b03909116905b85811015610afa57868682818110610928576109286156a0565b905060200281019061093a91906156b4565b6109489060208101906156d2565b905087878381811061095c5761095c6156a0565b905060200281019061096e91906156b4565b61097890806156d2565b905014610998576040516343714afd60e01b815260040160405180910390fd5b5f610a0233848a8a868181106109b0576109b06156a0565b90506020028101906109c291906156b4565b6109cc90806156d2565b808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525061243592505050565b9050610ad433848a8a86818110610a1b57610a1b6156a0565b9050602002810190610a2d91906156b4565b610a3790806156d2565b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152508e92508d9150889050818110610a7c57610a7c6156a0565b9050602002810190610a8e91906156b4565b610a9c9060208101906156d2565b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250889250612587915050565b848381518110610ae657610ae66156a0565b60209081029190910101525060010161090e565b5050600160c955949350505050565b610b11612b22565b6066548181168114610b365760405163c61dca5d60e01b815260040160405180910390fd5b610b3f82612bc5565b5050565b6001600160a01b038084165f908152609a60205260408120546060921690610b6c868387612435565b90505f85516001600160401b03811115610b8857610b88614ba2565b604051908082528060200260200182016040528015610bb1578160200160208202803683370190505b5090505f5b8651811015610c96576001600160a01b0388165f90815260a260205260408120885182908a9085908110610bec57610bec6156a0565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f206040518060200160405290815f820154815250509050610c70878381518110610c3e57610c3e6156a0565b6020026020010151858481518110610c5857610c586156a0565b602002602001015183612c029092919063ffffffff16565b838381518110610c8257610c826156a0565b602090810291909101015250600101610bb6565b50925050505b9392505050565b610cab6123dc565b610cb433610f4a565b15610cd257604051633bf2b50360e11b815260040160405180910390fd5b604051632b6241f360e11b815233600482015263ffffffff841660248201527f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b0316906356c483e6906044015f604051808303815f87803b158015610d3c575f5ffd5b505af1158015610d4e573d5f5f3e3d5ffd5b50505050610d5c3385612c20565b610d663333612c82565b6040516001600160a01b038516815233907fa453db612af59e5521d6ab9284dc3e2d06af286eb1b1b7b771fce4716c19f2c19060200160405180910390a2336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908383604051610ddf929190615717565b60405180910390a2610df1600160c955565b50505050565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb607508161480610e565750336001600160a01b037f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b116145b610e735760405163045206a560e21b815260040160405180910390fd5b610e7b6123dc565b6001600160a01b038481165f908152609a602052604080822054905163152667d960e31b8152908316600482018190528684166024830152927f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063a9333ec890604401602060405180830381865afa158015610efb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1f9190615745565b90505f610f2d878784612f0b565b9050610f3d838888888886612fed565b505050610df1600160c955565b6001600160a01b039081165f908152609a602052604090205416151590565b81610f7381613132565b610f905760405163932d94f760e01b815260040160405180910390fd5b610f986123dc565b610fa1836117ae565b610fbe576040516325ec6c1f60e01b815260040160405180910390fd5b610fc88383612c20565b610fd2600160c955565b505050565b60606110027f76312e302e3000000000000000000000000000000000000000000000000000066131dc565b905090565b61100f612b22565b6110195f19612bc5565b565b5f8160405160200161102d9190615421565b604051602081830303815290604052805190602001209050919050565b5f336001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed1614611094576040516323d871a560e01b815260040160405180910390fd5b61109c6123dc565b6001600160a01b038088165f9081526098602090815260408083209388168352929052908120546110da906001600160401b03808716908616613219565b90505f6110e989878787613231565b90506110f58183615774565b9250611103895f88856132ee565b604080516001600160a01b038881168252602082018690528b16917fdd611f4ef63f4385f1756c86ce1f1f389a9013ba6fa07daba8528291bc2d3c30910160405180910390a261115286613368565b6001600160a01b0316633fb99ca5898989876040518563ffffffff1660e01b81526004016111839493929190615787565b5f604051808303815f87803b15801561119a575f5ffd5b505af11580156111ac573d5f5f3e3d5ffd5b50505050505061088d600160c955565b6111c4614940565b60606111cf836133da565b9094909350915050565b6060805f6111e68461224c565b8051909150806001600160401b0381111561120357611203614ba2565b60405190808252806020026020018201604052801561123c57816020015b611229614940565b8152602001906001900390816112215790505b509350806001600160401b0381111561125757611257614ba2565b60405190808252806020026020018201604052801561128a57816020015b60608152602001906001900390816112755790505b5092505f5b818110156112fb576112b98382815181106112ac576112ac6156a0565b60200260200101516133da565b8683815181106112cb576112cb6156a0565b602002602001018684815181106112e4576112e46156a0565b60209081029190910101919091525260010161128f565b505050915091565b336001600160a01b037f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b1161461134c57604051633213a66160e21b815260040160405180910390fd5b6113546123dc565b61135d83610f4a565b15610fc8576001600160a01b038381165f908152609a602052604080822054905163152667d960e31b81529083166004820181905273beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06024830152927f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063a9333ec890604401602060405180830381865afa1580156113f4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114189190615745565b6001600160a01b0386165f90815260a26020908152604080832073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac084528252808320815192830190915254815291925061147e866114766001600160401b0380871690891661362d565b849190613641565b90506114a0848873beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0846132ee565b50505050610fd2600160c955565b6040516394f649dd60e01b81526001600160a01b03828116600483015260609182915f9182917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750816906394f649dd906024015f60405180830381865afa15801561151a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526115419190810190615837565b60405163fe243a1760e01b81526001600160a01b03888116600483015273beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac060248301529294509092505f917f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b1169063fe243a1790604401602060405180830381865afa1580156115c7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115eb91906158f2565b9050805f036115ff57509094909350915050565b5f8351600161160e9190615774565b6001600160401b0381111561162557611625614ba2565b60405190808252806020026020018201604052801561164e578160200160208202803683370190505b5090505f845160016116609190615774565b6001600160401b0381111561167757611677614ba2565b6040519080825280602002602001820160405280156116a0578160200160208202803683370190505b50905073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0828651815181106116cb576116cb6156a0565b60200260200101906001600160a01b031690816001600160a01b03168152505082818651815181106116ff576116ff6156a0565b60209081029190910101525f5b85518110156117a057858181518110611727576117276156a0565b6020026020010151838281518110611741576117416156a0565b60200260200101906001600160a01b031690816001600160a01b031681525050848181518110611773576117736156a0565b602002602001015182828151811061178d5761178d6156a0565b602090810291909101015260010161170c565b509097909650945050505050565b5f6001600160a01b038216158015906117e057506001600160a01b038083165f818152609a6020526040902054909116145b92915050565b60405163152667d960e31b81526001600160a01b03838116600483015282811660248301525f9182917f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063a9333ec890604401602060405180830381865afa158015611856573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061187a9190615745565b90506118888484835f613231565b949350505050565b8261189a81613132565b6118b75760405163932d94f760e01b815260040160405180910390fd5b6118c0846117ae565b6118dd576040516325ec6c1f60e01b815260040160405180910390fd5b836001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908484604051611918929190615717565b60405180910390a250505050565b60605f82516001600160401b0381111561194257611942614ba2565b60405190808252806020026020018201604052801561196b578160200160208202803683370190505b5090505f5b83518110156119f4576001600160a01b0385165f90815260986020526040812085519091908690849081106119a7576119a76156a0565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20548282815181106119e1576119e16156a0565b6020908102919091010152600101611970565b509392505050565b6002611a07816123ae565b611a0f6123dc565b855f5b81811015611aa257611a9a898983818110611a2f57611a2f6156a0565b9050602002810190611a419190615909565b611a4a9061591d565b888884818110611a5c57611a5c6156a0565b9050602002810190611a6e91906156d2565b888886818110611a8057611a806156a0565b9050602002016020810190611a959190615928565b61365f565b600101611a12565b5050611aae600160c955565b50505050505050565b611abf614940565b5f82815260a46020908152604091829020825160e08101845281546001600160a01b03908116825260018301548116828501526002830154168185015260038201546060820152600482015463ffffffff1660808201526005820180548551818602810186019096528086529194929360a08601939290830182828015611b6d57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611b4f575b5050505050815260200160068201805480602002602001604051908101604052809291908181526020018280548015611bc357602002820191905f5260205f20905b815481526020019060010190808311611baf575b5050505050815250509050919050565b6060611bde33611eb4565b9050610c9c848484612015565b6001600160a01b038083165f90815260a260209081526040808320938516835292815282822083519182019093529154825290610c9c90613aa1565b60608082516001600160401b03811115611c4357611c43614ba2565b604051908082528060200260200182016040528015611c6c578160200160208202803683370190505b50915082516001600160401b03811115611c8857611c88614ba2565b604051908082528060200260200182016040528015611cb1578160200160208202803683370190505b506001600160a01b038086165f908152609a6020526040812054929350911690611cdc868387612435565b90505f5b8551811015611ea9575f611d0c878381518110611cff57611cff6156a0565b6020026020010151613368565b9050806001600160a01b031663fe243a1789898581518110611d3057611d306156a0565b60200260200101516040518363ffffffff1660e01b8152600401611d6a9291906001600160a01b0392831681529116602082015260400190565b602060405180830381865afa158015611d85573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611da991906158f2565b858381518110611dbb57611dbb6156a0565b6020026020010181815250505f60a25f8a6001600160a01b03166001600160a01b031681526020019081526020015f205f898581518110611dfe57611dfe6156a0565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f206040518060200160405290815f820154815250509050611e82868481518110611e5057611e506156a0565b6020026020010151858581518110611e6a57611e6a6156a0565b6020026020010151836136419092919063ffffffff16565b878481518110611e9457611e946156a0565b60209081029190910101525050600101611ce0565b5050505b9250929050565b6060611ebe6123dc565b611ec782610f4a565b611ee45760405163a5c7c44560e01b815260040160405180910390fd5b611eed826117ae565b15611f0b576040516311ca333560e31b815260040160405180910390fd5b336001600160a01b03831614611fc3576001600160a01b038083165f908152609a602052604090205416611f3e81613132565b80611f6457506001600160a01b038181165f908152609960205260409020600101541633145b611f8157604051631e499a2360e11b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03167ff0eddf07e6ea14f388b47e1e94a0f464ecbd9eed4171130e0fc0e99fb4030a8a60405160405180910390a3505b611fcc82613ac0565b9050611fd8600160c955565b919050565b6002611fe8816123ae565b611ff06123dc565b612004611ffc8661591d565b85858561365f565b61200e600160c955565b5050505050565b61201d6123dc565b61202633610f4a565b1561204457604051633bf2b50360e11b815260040160405180910390fd5b61204d836117ae565b61206a576040516325ec6c1f60e01b815260040160405180910390fd5b61207633848484613d00565b610fc83384612c82565b60605f83516001600160401b0381111561209c5761209c614ba2565b6040519080825280602002602001820160405280156120cf57816020015b60608152602001906001900390816120ba5790505b5090505f5b84518110156119f4576121008582815181106120f2576120f26156a0565b602002602001015185611926565b828281518110612112576121126156a0565b60209081029190910101526001016120d4565b60408051808201909152600a81526922b4b3b2b72630bcb2b960b11b6020909101525f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea612192613dbf565b805160209182012060408051928301949094529281019190915260608101919091524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6121e6613e34565b6066548019821981161461220d5760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020015b60405180910390a25050565b6001600160a01b0381165f90815260a3602052604090206060906117e090613ee5565b5f54610100900460ff161580801561228d57505f54600160ff909116105b806122a65750303b1580156122a657505f5460ff166001145b61230e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff19166001179055801561232f575f805461ff0019166101001790555b61233882612bc5565b8015610b3f575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b5f612389612125565b60405161190160f01b602082015260228101919091526042810183905260620161102d565b606654600160ff83161b908116036123d95760405163840a48d560e01b815260040160405180910390fd5b50565b600260c9540361242e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401612305565b600260c955565b60605f82516001600160401b0381111561245157612451614ba2565b60405190808252806020026020018201604052801561247a578160200160208202803683370190505b5090505f7f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b031663547afb8786866040518363ffffffff1660e01b81526004016124cc929190615943565b5f60405180830381865afa1580156124e6573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261250d9190810190615966565b90505f5b845181101561257c5761255787868381518110612530576125306156a0565b602002602001015184848151811061254a5761254a6156a0565b6020026020010151612f0b565b838281518110612569576125696156a0565b6020908102919091010152600101612511565b509095945050505050565b5f6001600160a01b0386166125af576040516339b190bb60e11b815260040160405180910390fd5b83515f036125d05760405163796cc52560e01b815260040160405180910390fd5b5f84516001600160401b038111156125ea576125ea614ba2565b604051908082528060200260200182016040528015612613578160200160208202803683370190505b5090505f85516001600160401b0381111561263057612630614ba2565b604051908082528060200260200182016040528015612659578160200160208202803683370190505b5090505f5b8651811015612955575f61267d888381518110611cff57611cff6156a0565b90505f60a25f8c6001600160a01b03166001600160a01b031681526020019081526020015f205f8a85815181106126b6576126b66156a0565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20905061272f8884815181106126f4576126f46156a0565b602002602001015188858151811061270e5761270e6156a0565b60209081029190910181015160408051928301905284548252909190613641565b848481518110612741576127416156a0565b602002602001018181525050612780888481518110612762576127626156a0565b60209081029190910181015160408051928301905283548252613ef1565b858481518110612792576127926156a0565b60209081029190910101526001600160a01b038a1615612827576127e98a8a85815181106127c2576127c26156a0565b60200260200101518786815181106127dc576127dc6156a0565b6020026020010151613f05565b6128278a8c8b8681518110612800576128006156a0565b602002602001015187878151811061281a5761281a6156a0565b60200260200101516132ee565b5f826001600160a01b031663724af4238d8c878151811061284a5761284a6156a0565b60200260200101518c8881518110612864576128646156a0565b60200260200101516040518463ffffffff1660e01b815260040161288a939291906159f5565b6020604051808303815f875af11580156128a6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ca91906158f2565b9050805f03612947575f82557f8be932bac54561f27260f95463d9b8ab37e06b2842e5ee2404157cc13df6eb8f8c8b868151811061290a5761290a6156a0565b602002602001015161292f856040518060200160405290815f82015481525050613aa1565b60405161293e939291906159f5565b60405180910390a15b50505080600101905061265e565b506001600160a01b0388165f908152609f6020526040812080549182919061297c83615a19565b91905055505f6040518060e001604052808b6001600160a01b031681526020018a6001600160a01b031681526020018b6001600160a01b031681526020018381526020014363ffffffff1681526020018981526020018581525090505f6129e28261101b565b5f818152609e602090815260408083208054600160ff19909116811790915560a4835292819020865181546001600160a01b03199081166001600160a01b039283161783558885015195830180548216968316969096179095559187015160028201805490951692169190911790925560608501516003830155608085015160048301805463ffffffff191663ffffffff90921691909117905560a085015180519394508593612a989260058501920190614999565b5060c08201518051612ab49160068401916020909101906149fc565b5050506001600160a01b038b165f90815260a360205260409020612ad89082613f6f565b507f26b2aae26516e8719ef50ea2f6831a2efbd4e37dccdf0f6936b27bc08e793e30818386604051612b0c93929190615a31565b60405180910390a19a9950505050505050505050565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa158015612b84573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba89190615a5b565b61101957604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b5f61188882612c1a612c1387613aa1565b8690613f7a565b90613f7a565b6001600160a01b038281165f8181526099602090815260409182902060010180546001600160a01b0319169486169485179055905192835290917f773b54c04d756fcc5e678111f7d730de3be98192000799eee3d63716055a87c69101612240565b5f612c8c816123ae565b5f5f612c97856114ae565b915091505f612ca75f8685612435565b6001600160a01b038781165f818152609a602052604080822080546001600160a01b031916948b16948517905551939450919290917fc3ee9f2e5fda98e8066a1f745b2df9285f416fe98cf2559cd21484b3d874330491a35f5b8351811015611aae5773beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06001600160a01b0316848281518110612d3a57612d3a6156a0565b60200260200101516001600160a01b031603612eaa5760405163a3d75e0960e01b81526001600160a01b0388811660048301525f917f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b19091169063a3d75e0990602401602060405180830381865afa158015612db8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ddc9190615745565b90505f60a25f8a6001600160a01b03166001600160a01b031681526020019081526020015f205f878581518110612e1557612e156156a0565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f206040518060200160405290815f820154815250509050612e89858481518110612e6757612e676156a0565b6020026020010151836001600160401b0316836136419092919063ffffffff16565b858481518110612e9b57612e9b6156a0565b60200260200101818152505050505b612f038688868481518110612ec157612ec16156a0565b60200260200101515f878681518110612edc57612edc6156a0565b6020026020010151878781518110612ef657612ef66156a0565b6020026020010151612fed565b600101612d01565b5f73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeabf196001600160a01b03841601612fdd5760405163a3d75e0960e01b81526001600160a01b0385811660048301525f917f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b19091169063a3d75e0990602401602060405180830381865afa158015612f99573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fbd9190615745565b9050612fd56001600160401b0384811690831661362d565b915050610c9c565b506001600160401b031692915050565b805f0361300d57604051630a33bc6960e21b815260040160405180910390fd5b811561312a576001600160a01b038086165f90815260a26020908152604080832093881683529290522061304381858585613f8e565b6040805160208101909152815481527f8be932bac54561f27260f95463d9b8ab37e06b2842e5ee2404157cc13df6eb8f908790879061308190613aa1565b604051613090939291906159f5565b60405180910390a16130a186610f4a565b15611aae576001600160a01b038088165f908152609860209081526040808320938916835292905290812080548592906130dc908490615774565b92505081905550866001600160a01b03167f1ec042c965e2edd7107b51188ee0f383e22e76179041ab3a9d18ff151405166c878786604051613120939291906159f5565b60405180910390a2505b505050505050565b604051631beb2b9760e31b81526001600160a01b0382811660048301523360248301523060448301525f80356001600160e01b0319166064840152917f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c9091169063df595cb8906084016020604051808303815f875af11580156131b8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117e09190615a5b565b60605f6131e883614024565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f613227848385600161404b565b6118889085615a76565b6001600160a01b038085165f90815260a56020908152604080832093871683529290529081208190613262906140a6565b90505f6132c860016132947f000000000000000000000000000000000000000000000000000000000000003243615a89565b61329e9190615a89565b6001600160a01b03808a165f90815260a560209081526040808320938c16835292905220906140c0565b90505f6132d58284615a76565b90506132e28187876140dc565b98975050505050505050565b6001600160a01b038085165f90815260986020908152604080832093861683529290529081208054839290613324908490615a76565b92505081905550836001600160a01b03167f6909600037b75d7b4733aedd815442b5ec018a827751c832aaff64eba5d6d2dd848484604051611918939291906159f5565b5f6001600160a01b03821673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0146133b3577f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075086117e0565b7f000000000000000000000000959922be3caee4b8cd9a407cc3ac1c251c2007b192915050565b6133e2614940565b5f82815260a46020908152604091829020825160e08101845281546001600160a01b0390811682526001830154811682850152600283015416818501526003820154606082810191909152600483015463ffffffff1660808301526005830180548651818702810187019097528087529195929460a0860193929083018282801561349457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311613476575b50505050508152602001600682018054806020026020016040519081016040528092919081815260200182805480156134ea57602002820191905f5260205f20905b8154815260200190600101908083116134d6575b50505050508152505091508160a00151516001600160401b0381111561351257613512614ba2565b60405190808252806020026020018201604052801561353b578160200160208202803683370190505b5090505f7f0000000000000000000000000000000000000000000000000000000000000032836080015161356f9190615aa5565b90505f4363ffffffff168263ffffffff16106135a05761359b845f015185602001518660a00151612435565b6135b7565b6135b7845f015185602001518660a00151856140fa565b90505f5b8460a00151518110156112fb576136088560c0015182815181106135e1576135e16156a0565b60200260200101518383815181106135fb576135fb6156a0565b6020026020010151614228565b84828151811061361a5761361a6156a0565b60209081029190910101526001016135bb565b5f610c9c8383670de0b6b3a7640000614233565b5f6118888261365961365287613aa1565b869061362d565b9061362d565b60a0840151518214613684576040516343714afd60e01b815260040160405180910390fd5b83604001516001600160a01b0316336001600160a01b0316146136ba576040516316110d3560e21b815260040160405180910390fd5b5f6136c48561101b565b5f818152609e602052604090205490915060ff166136f5576040516387c9d21960e01b815260040160405180910390fd5b60605f7f000000000000000000000000000000000000000000000000000000000000003287608001516137289190615aa5565b90508063ffffffff164363ffffffff1611613756576040516378f67ae160e11b815260040160405180910390fd5b61376d875f015188602001518960a00151846140fa565b87516001600160a01b03165f90815260a360205260409020909250613793915083614318565b505f82815260a46020526040812080546001600160a01b031990811682556001820180548216905560028201805490911690556003810182905560048101805463ffffffff19169055906137ea6005830182614a35565b6137f7600683015f614a35565b50505f828152609e602052604090819020805460ff19169055517f1f40400889274ed07b24845e5054a87a0cab969eb1277aafe61ae352e7c32a00906138409084815260200190565b60405180910390a185516001600160a01b039081165f908152609a6020526040812054885160a08a0151919093169261387a918490612435565b90505f5b8860a0015151811015613a96575f6138a58a60a001518381518110611cff57611cff6156a0565b90505f6138db8b60c0015184815181106138c1576138c16156a0565b60200260200101518785815181106135fb576135fb6156a0565b9050805f036138eb575050613a8e565b87156139b957816001600160a01b0316632eae418c8c5f01518d60a00151868151811061391a5761391a6156a0565b60200260200101518d8d88818110613934576139346156a0565b90506020020160208101906139499190614ed1565b60405160e085901b6001600160e01b03191681526001600160a01b03938416600482015291831660248301529091166044820152606481018490526084015f604051808303815f87803b15801561399e575f5ffd5b505af11580156139b0573d5f5f3e3d5ffd5b50505050613a8b565b5f5f836001600160a01b03166350ff72258e5f01518f60a0015188815181106139e4576139e46156a0565b6020026020010151866040518463ffffffff1660e01b8152600401613a0b939291906159f5565b60408051808303815f875af1158015613a26573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a4a9190615ac1565b91509150613a88878e5f01518f60a001518881518110613a6c57613a6c6156a0565b602002602001015185858b8b81518110612ef657612ef66156a0565b50505b50505b60010161387e565b505050505050505050565b80515f9015613ab15781516117e0565b670de0b6b3a764000092915050565b60606001613acd816123ae565b6001600160a01b038084165f818152609a602052604080822080546001600160a01b0319811690915590519316928392917ffee30966a256b71e14bc0ebfc94315e28ef4a97a7131a9e2b7a310a73af4467691a35f5f613b2c866114ae565b9150915081515f03613b4057505050613cfa565b81516001600160401b03811115613b5957613b59614ba2565b604051908082528060200260200182016040528015613b82578160200160208202803683370190505b5094505f613b91878585612435565b90505f5b8351811015613cf4576040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f92915060208083019080368337019050509050868481518110613c1557613c156156a0565b6020026020010151835f81518110613c2f57613c2f6156a0565b60200260200101906001600160a01b031690816001600160a01b031681525050858481518110613c6157613c616156a0565b6020026020010151825f81518110613c7b57613c7b6156a0565b602002602001018181525050848481518110613c9957613c996156a0565b6020026020010151815f81518110613cb357613cb36156a0565b602002602001018181525050613ccc8b89858585612587565b8a8581518110613cde57613cde6156a0565b6020908102919091010152505050600101613b95565b50505050505b50919050565b6001600160a01b038084165f908152609960205260409020600101541680613d285750610df1565b6001600160a01b0381165f908152609c6020908152604080832085845290915290205460ff1615613d6c57604051630d4c4c9160e21b815260040160405180910390fd5b6001600160a01b0381165f908152609c602090815260408083208584528252909120805460ff1916600117905583015161200e908290613db390889088908490889061080f565b85516020870151614323565b60605f613deb7f76312e302e3000000000000000000000000000000000000000000000000000066131dc565b9050805f81518110613dff57613dff6156a0565b016020908101516040516001600160f81b03199091169181019190915260210160405160208183030381529060405291505090565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e90573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613eb49190615ae3565b6001600160a01b0316336001600160a01b0316146110195760405163794821ff60e01b815260040160405180910390fd5b60605f610c9c83614375565b5f610c9c613efe84613aa1565b839061362d565b6001600160a01b038084165f90815260a5602090815260408083209386168352929052908120613f34906140a6565b9050610df143613f448484615774565b6001600160a01b038088165f90815260a560209081526040808320938a1683529290522091906143ce565b5f610c9c83836143d9565b5f610c9c83670de0b6b3a764000084614233565b825f03613fba57604080516020810190915284548152613fb3908290612c1a90613aa1565b8455610df1565b6040805160208101909152845481525f90613fd6908584613641565b90505f613fe38483615774565b90505f613ffe84612c1a613ff7888a615774565b8590613f7a565b80885590505f819003611aae5760405163172cec7360e31b815260040160405180910390fd5b5f60ff8216601f8111156117e057604051632cd44ac360e21b815260040160405180910390fd5b5f5f614058868686614233565b9050600183600281111561406e5761406e615afe565b14801561408a57505f848061408557614085615b12565b868809115b1561409d5761409a600182615774565b90505b95945050505050565b5f6140b18282614425565b6001600160e01b031692915050565b5f6140cc83838361446a565b6001600160e01b03169392505050565b5f6118886140ea8385615b26565b85906001600160401b031661362d565b60605f83516001600160401b0381111561411657614116614ba2565b60405190808252806020026020018201604052801561413f578160200160208202803683370190505b5090505f7f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b03166394d7d00c8787876040518463ffffffff1660e01b815260040161419393929190615b45565b5f60405180830381865afa1580156141ad573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526141d49190810190615966565b90505f5b855181101561421c576141f788878381518110612530576125306156a0565b838281518110614209576142096156a0565b60209081029190910101526001016141d8565b50909695505050505050565b5f610c9c838361362d565b5f80805f19858709858702925082811083820303915050805f0361426a5783828161426057614260615b12565b0492505050610c9c565b8084116142b15760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401612305565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f610c9c83836144b3565b4281101561434457604051630819bdcd60e01b815260040160405180910390fd5b6143586001600160a01b0385168484614596565b610df157604051638baa579f60e01b815260040160405180910390fd5b6060815f018054806020026020016040519081016040528092919081815260200182805480156143c257602002820191905f5260205f20905b8154815260200190600101908083116143ae575b50505050509050919050565b610fd28383836145ea565b5f81815260018301602052604081205461441e57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556117e0565b505f6117e0565b81545f9080156144625761444b8461443e600184615a76565b5f91825260209091200190565b5464010000000090046001600160e01b0316611888565b509092915050565b82545f908161447b868683856146f0565b905080156144a9576144928661443e600184615a76565b5464010000000090046001600160e01b031661088d565b5091949350505050565b5f818152600183016020526040812054801561458d575f6144d5600183615a76565b85549091505f906144e890600190615a76565b9050818114614547575f865f018281548110614506576145066156a0565b905f5260205f200154905080875f018481548110614526576145266156a0565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061455857614558615b7e565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506117e0565b5f9150506117e0565b5f5f5f6145a38585614743565b90925090505f8160048111156145bb576145bb615afe565b1480156145d95750856001600160a01b0316826001600160a01b0316145b8061088d575061088d868686614782565b825480156146a2575f6146028561443e600185615a76565b60408051808201909152905463ffffffff8082168084526401000000009092046001600160e01b0316602084015291925090851610156146555760405163151b8e3f60e11b815260040160405180910390fd5b805163ffffffff8086169116036146a057826146768661443e600186615a76565b80546001600160e01b03929092166401000000000263ffffffff9092169190911790555050505050565b505b506040805180820190915263ffffffff92831681526001600160e01b03918216602080830191825285546001810187555f968752952091519051909216640100000000029190921617910155565b5f5b818310156119f4575f6147058484614869565b5f8781526020902090915063ffffffff86169082015463ffffffff16111561472f5780925061473d565b61473a816001615774565b93505b506146f2565b5f5f8251604103614777576020830151604084015160608501515f1a61476b87828585614883565b94509450505050611ead565b505f90506002611ead565b5f5f5f856001600160a01b0316631626ba7e60e01b86866040516024016147aa929190615b92565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516147e89190615baa565b5f60405180830381855afa9150503d805f8114614820576040519150601f19603f3d011682016040523d82523d5f602084013e614825565b606091505b509150915081801561483957506020815110155b801561088d57508051630b135d3f60e11b9061485e90830160209081019084016158f2565b149695505050505050565b5f6148776002848418615bc0565b610c9c90848416615774565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156148b857505f90506003614937565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614909573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116614931575f60019250925050614937565b91505f90505b94509492505050565b6040518060e001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f63ffffffff16815260200160608152602001606081525090565b828054828255905f5260205f209081019282156149ec579160200282015b828111156149ec57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906149b7565b506149f8929150614a4c565b5090565b828054828255905f5260205f209081019282156149ec579160200282015b828111156149ec578251825591602001919060010190614a1a565b5080545f8255905f5260205f20908101906123d991905b5b808211156149f8575f8155600101614a4d565b6001600160a01b03811681146123d9575f5ffd5b8035611fd881614a60565b5f5f5f5f5f60a08688031215614a93575f5ffd5b8535614a9e81614a60565b94506020860135614aae81614a60565b93506040860135614abe81614a60565b94979396509394606081013594506080013592915050565b5f5f83601f840112614ae6575f5ffd5b5081356001600160401b03811115614afc575f5ffd5b6020830191508360208260051b8501011115611ead575f5ffd5b5f5f60208385031215614b27575f5ffd5b82356001600160401b03811115614b3c575f5ffd5b614b4885828601614ad6565b90969095509350505050565b602080825282518282018190525f918401906040840190835b8181101561257c578351835260209384019390920191600101614b6d565b5f60208284031215614b9b575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b60405160e081016001600160401b0381118282101715614bd857614bd8614ba2565b60405290565b604080519081016001600160401b0381118282101715614bd857614bd8614ba2565b604051601f8201601f191681016001600160401b0381118282101715614c2857614c28614ba2565b604052919050565b5f6001600160401b03821115614c4857614c48614ba2565b5060051b60200190565b5f82601f830112614c61575f5ffd5b8135614c74614c6f82614c30565b614c00565b8082825260208201915060208360051b860101925085831115614c95575f5ffd5b602085015b83811015614cbb578035614cad81614a60565b835260209283019201614c9a565b5095945050505050565b5f82601f830112614cd4575f5ffd5b8135614ce2614c6f82614c30565b8082825260208201915060208360051b860101925085831115614d03575f5ffd5b602085015b83811015614cbb578035835260209283019201614d08565b5f5f5f60608486031215614d32575f5ffd5b8335614d3d81614a60565b925060208401356001600160401b03811115614d57575f5ffd5b614d6386828701614c52565b92505060408401356001600160401b03811115614d7e575f5ffd5b614d8a86828701614cc5565b9150509250925092565b5f8151808452602084019350602083015f5b82811015614dc4578151865260209586019590910190600101614da6565b5093949350505050565b602081525f610c9c6020830184614d94565b803563ffffffff81168114611fd8575f5ffd5b5f5f83601f840112614e03575f5ffd5b5081356001600160401b03811115614e19575f5ffd5b602083019150836020828501011115611ead575f5ffd5b5f5f5f5f60608587031215614e43575f5ffd5b8435614e4e81614a60565b9350614e5c60208601614de0565b925060408501356001600160401b03811115614e76575f5ffd5b614e8287828801614df3565b95989497509550505050565b5f5f5f5f60808587031215614ea1575f5ffd5b8435614eac81614a60565b93506020850135614ebc81614a60565b93969395505050506040820135916060013590565b5f60208284031215614ee1575f5ffd5b8135610c9c81614a60565b5f5f60408385031215614efd575f5ffd5b8235614f0881614a60565b91506020830135614f1881614a60565b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c9c6020830184614f23565b5f60e08284031215614f73575f5ffd5b614f7b614bb6565b9050614f8682614a74565b8152614f9460208301614a74565b6020820152614fa560408301614a74565b604082015260608281013590820152614fc060808301614de0565b608082015260a08201356001600160401b03811115614fdd575f5ffd5b614fe984828501614c52565b60a08301525060c08201356001600160401b03811115615007575f5ffd5b61501384828501614cc5565b60c08301525092915050565b5f6020828403121561502f575f5ffd5b81356001600160401b03811115615044575f5ffd5b61188884828501614f63565b5f60208284031215615060575f5ffd5b813560ff81168114610c9c575f5ffd5b6001600160401b03811681146123d9575f5ffd5b5f5f5f5f5f5f86880360e081121561509a575f5ffd5b87356150a581614a60565b96506040601f19820112156150b8575f5ffd5b506020870194506060870135935060808701356150d481614a60565b925060a08701356150e481615070565b915060c08701356150f481615070565b809150509295509295509295565b5f8151808452602084019350602083015f5b82811015614dc45781516001600160a01b0316865260209586019590910190600101615114565b80516001600160a01b03908116835260208083015182169084015260408083015190911690830152606080820151908301526080808201515f916151869085018263ffffffff169052565b5060a082015160e060a08501526151a060e0850182615102565b905060c083015184820360c086015261409d8282614d94565b604081525f6151cb604083018561513b565b828103602084015261409d8185614d94565b5f82825180855260208501945060208160051b830101602085015f5b8381101561421c57601f19858403018852615215838351614d94565b60209889019890935091909101906001016151f9565b5f604082016040835280855180835260608501915060608160051b8601019250602087015f5b8281101561528257605f1987860301845261526d85835161513b565b94506020938401939190910190600101615251565b50505050828103602084015261409d81856151dd565b5f5f5f606084860312156152aa575f5ffd5b83356152b581614a60565b92506020840135915060408401356152cc81615070565b809150509250925092565b604081525f6151cb6040830185615102565b5f5f5f604084860312156152fb575f5ffd5b833561530681614a60565b925060208401356001600160401b03811115615320575f5ffd5b61532c86828701614df3565b9497909650939450505050565b5f5f6040838503121561534a575f5ffd5b823561535581614a60565b915060208301356001600160401b0381111561536f575f5ffd5b61537b85828601614c52565b9150509250929050565b5f5f5f5f5f5f6060878903121561539a575f5ffd5b86356001600160401b038111156153af575f5ffd5b6153bb89828a01614ad6565b90975095505060208701356001600160401b038111156153d9575f5ffd5b6153e589828a01614ad6565b90955093505060408701356001600160401b03811115615403575f5ffd5b61540f89828a01614ad6565b979a9699509497509295939492505050565b602081525f610c9c602083018461513b565b5f5f5f60608486031215615445575f5ffd5b833561545081614a60565b925060208401356001600160401b0381111561546a575f5ffd5b84016040818703121561547b575f5ffd5b615483614bde565b81356001600160401b03811115615498575f5ffd5b8201601f810188136154a8575f5ffd5b80356001600160401b038111156154c1576154c1614ba2565b6154d4601f8201601f1916602001614c00565b8181528960208385010111156154e8575f5ffd5b816020840160208301375f60209282018301528352928301359282019290925293969395505050506040919091013590565b5f5f6040838503121561552b575f5ffd5b823561553681614a60565b946020939093013593505050565b604081525f6151cb6040830185614d94565b80151581146123d9575f5ffd5b5f5f5f5f60608587031215615576575f5ffd5b84356001600160401b0381111561558b575f5ffd5b850160e0818803121561559c575f5ffd5b935060208501356001600160401b038111156155b6575f5ffd5b6155c287828801614ad6565b90945092505060408501356155d681615556565b939692955090935050565b5f5f604083850312156155f2575f5ffd5b82356001600160401b03811115615607575f5ffd5b8301601f81018513615617575f5ffd5b8035615625614c6f82614c30565b8082825260208201915060208360051b850101925087831115615646575f5ffd5b6020840193505b8284101561567157833561566081614a60565b82526020938401939091019061564d565b945050505060208301356001600160401b0381111561536f575f5ffd5b602081525f610c9c60208301846151dd565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e198336030181126156c8575f5ffd5b9190910192915050565b5f5f8335601e198436030181126156e7575f5ffd5b8301803591506001600160401b03821115615700575f5ffd5b6020019150600581901b3603821315611ead575f5ffd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60208284031215615755575f5ffd5b8151610c9c81615070565b634e487b7160e01b5f52601160045260245ffd5b808201808211156117e0576117e0615760565b60a08101853561579681614a60565b6001600160a01b0316825263ffffffff6157b260208801614de0565b16602083015260408201949094526001600160a01b03929092166060830152608090910152919050565b5f82601f8301126157eb575f5ffd5b81516157f9614c6f82614c30565b8082825260208201915060208360051b86010192508583111561581a575f5ffd5b602085015b83811015614cbb57805183526020928301920161581f565b5f5f60408385031215615848575f5ffd5b82516001600160401b0381111561585d575f5ffd5b8301601f8101851361586d575f5ffd5b805161587b614c6f82614c30565b8082825260208201915060208360051b85010192508783111561589c575f5ffd5b6020840193505b828410156158c75783516158b681614a60565b8252602093840193909101906158a3565b8095505050505060208301516001600160401b038111156158e6575f5ffd5b61537b858286016157dc565b5f60208284031215615902575f5ffd5b5051919050565b5f823560de198336030181126156c8575f5ffd5b5f6117e03683614f63565b5f60208284031215615938575f5ffd5b8135610c9c81615556565b6001600160a01b03831681526040602082018190525f9061188890830184615102565b5f60208284031215615976575f5ffd5b81516001600160401b0381111561598b575f5ffd5b8201601f8101841361599b575f5ffd5b80516159a9614c6f82614c30565b8082825260208201915060208360051b8501019250868311156159ca575f5ffd5b6020840193505b8284101561088d5783516159e481615070565b8252602093840193909101906159d1565b6001600160a01b039384168152919092166020820152604081019190915260600190565b5f60018201615a2a57615a2a615760565b5060010190565b838152606060208201525f615a49606083018561513b565b828103604084015261088d8185614d94565b5f60208284031215615a6b575f5ffd5b8151610c9c81615556565b818103818111156117e0576117e0615760565b63ffffffff82811682821603908111156117e0576117e0615760565b63ffffffff81811683821601908111156117e0576117e0615760565b5f5f60408385031215615ad2575f5ffd5b505080516020909101519092909150565b5f60208284031215615af3575f5ffd5b8151610c9c81614a60565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b6001600160401b0382811682821603908111156117e0576117e0615760565b6001600160a01b03841681526060602082018190525f90615b6890830185615102565b905063ffffffff83166040830152949350505050565b634e487b7160e01b5f52603160045260245ffd5b828152604060208201525f6118886040830184614f23565b5f82518060208501845e5f920191825250919050565b5f82615bda57634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220a9eb7922fcc5d3342ff9b5ab7a8bf23e57a11428d7ebabb9151464adde75010f64736f6c634300081c003300000000000000000000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "18": { - "address": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf", - "code": "0x608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c806366ae69a011610093578063a77cf3d211610063578063a77cf3d214610238578063ad209a9b1461024b578063bb51f1eb14610272578063df0dd0d514610285575f5ffd5b806366ae69a0146101b05780636f55bd32146101db5780638ab81d1314610202578063a401662b14610215575f5ffd5b806341c9634e116100ce57806341c9634e1461013e578063591d99ee146101545780635da57fe91461017b578063623b223d1461019b575f5ffd5b80630a7c8faa146100f45780632cdea7171461011e5780633666751314610136575b5f5ffd5b610100610dad60f31b81565b6040516001600160f01b031990911681526020015b60405180910390f35b61012661030f565b60405161011594939291906124a2565b610126610390565b6101465f5481565b604051908152602001610115565b6101467f000000000000000000000000000000000000000000000000000000000000000481565b61018e610189366004612572565b61040f565b60405161011591906125b9565b6101ae6101a9366004612621565b610447565b005b6001546101c3906001600160401b031681565b6040516001600160401b039091168152602001610115565b6101467f000000000000000000000000000000000000000000000000000000000000000281565b61018e610210366004612702565b6107d9565b610228610223366004612749565b6108b0565b6040519015158152602001610115565b6101ae610246366004612797565b6108bf565b6101467f000000000000000000000000000000000000000000000000000000000000001881565b6101ae6102803660046127ae565b610a37565b6102d3610293366004612797565b600a6020525f90815260409020805460018201546002909201546001600160401b0382169263ffffffff600160401b8404811693600160601b9004169185565b604080516001600160401b0396909616865263ffffffff948516602087015292909316918401919091526060830152608082015260a001610115565b6002805460035460408051600480546060602082028401810185529383018181526001600160801b0380881698600160801b9098041696948492849184018282801561037857602002820191905f5260205f20905b815481526020019060010190808311610364575b50505050508152602001600182015481525050905084565b6006805460075460408051600880546060602082028401810185529383018181526001600160801b0380881698600160801b9098041696948492849184018282801561037857602002820191905f5260205f20908154815260200190600101908083116103645750505050508152602001600182015481525050905084565b60608282101561043257604051635c85a0e760e01b815260040160405180910390fd5b61043d848484610ea1565b90505b9392505050565b5f6104518a610f2b565b8051906020012090505f61046e33835f9182526020526040902090565b905061047c818c8c8c61101d565b5f5f90505f6002905060065f015f9054906101000a90046001600160801b03166001600160801b03168d60200160208101906104b89190612843565b6001600160401b0316036104d2575060019050600661052c565b60025f015f9054906101000a90046001600160801b03166001600160801b03168d60200160208101906105059190612843565b6001600160401b03161461052c57604051636033c4fd60e11b815260040160405180910390fd5b61053b84848e8e858f8f61110c565b5f6105458e6112c2565b905082156106d657600654610564906001600160801b0316600161287d565b6001600160801b031661057d60808b0160608c01612843565b6001600160401b0316146105a3576040516263964160e91b815260040160405180910390fd5b5f6105c0826105b18c6113f4565b805190602001208b8b8b6114a8565b9050806105e05760405163128597bb60e01b815260040160405180910390fd5b60068054600160801b8082046001600160801b0390811690910291161760029081556007546003556008805460049061061c908290849061240d565b5060019182015491015550610639905060808b0160608c01612843565b600680546001600160801b0319166001600160401b039290921691909117905561066960a08b0160808c0161289c565b600680546001600160801b031663ffffffff92909216600160801b0291909117905560a08a0180356007556106b0906106a59060808d0161289c565b63ffffffff16611517565b805180516008916106c691839160200190612455565b5060208201518160010155905050505b5f8190556106e760208f018f61289c565b63ffffffff1660015f6101000a8154816001600160401b0302191690836001600160401b03160217905550600a5f8581526020019081526020015f205f5f82015f6101000a8154906001600160401b0302191690555f820160086101000a81549063ffffffff02191690555f8201600c6101000a81549063ffffffff0219169055600182015f9055600282015f905550507fd95fe1258d152dc91c81b09380498adc76ed36a6079bcb2ed31eff622ae2d0f1818f5f0160208101906107ac919061289c565b6040805192835263ffffffff90911660208301520160405180910390a15050505050505050505050505050565b60605f600a5f6107f233885f9182526020526040902090565b81526020019081526020015f20905083836040516020016108149291906128bf565b6040516020818303038152906040528051906020012081600201541461084d576040516333b4605560e11b815260040160405180910390fd5b6108a781600101548585808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050855463ffffffff600160401b820481169350600160601b9091041690506115bc565b95945050505050565b5f6108a75f54868686866114a8565b335f9081526020829052604081205f818152600a602052604081208054929350916001600160401b03169003610908576040516319a1b6d960e21b815260040160405180910390fd5b60018101541561092b5760405163e31d900560e01b815260040160405180910390fd5b8054610961907f0000000000000000000000000000000000000000000000000000000000000004906001600160401b03166128e6565b4310156109815760405163c77c194960e01b815260040160405180910390fd5b80547f0000000000000000000000000000000000000000000000000000000000000018906109d9907f0000000000000000000000000000000000000000000000000000000000000004906001600160401b03166128e6565b6109e391906128e6565b431115610a2c575f828152600a602052604080822080546001600160801b0319168155600181018390556002019190915580516340d3544760e01b815290519081900360040190fd5b446001909101555050565b6001546001600160401b0316610a50602086018661289c565b63ffffffff1611610a74576040516303d618e560e41b815260040160405180910390fd5b600280545f906001600160801b0316610a936040880160208901612843565b6001600160401b031603610ad757610ab0600460608501356116a4565b9050610ad26060840135610ac961ffff8416600161170e565b6004919061172c565b610b54565b6006546001600160801b0316610af36040880160208901612843565b6001600160401b031603610b3b57610b10600860608501356116a4565b9050610b326060840135610b2961ffff8416600161170e565b6008919061172c565b60069150610b54565b604051636033c4fd60e11b815260040160405180910390fd5b610b7f82610b6860a08601608087016128f9565b6060860135610b7a60a088018861291f565b6117d3565b1580610bc75750610bc58585808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152505050506060850135611842565b155b15610be557604051637000a9fd60e11b815260040160405180910390fd5b5f610bef87610f2b565b80516020909101209050610c0960a08501608086016128f9565b6001600160a01b0316610c3282610c236020880188612964565b87602001358860400135611886565b6001600160a01b031614610c5957604051638baa579f60e01b815260040160405180910390fd5b8254610c7490600160801b90046001600160801b03166118ac565b85141580610ce857508254610c9890600160801b90046001600160801b03166118c5565b610ce68787808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508754600160801b90046001600160801b031691506118f49050565b105b15610d06576040516333b4605560e11b815260040160405180910390fd5b6040805160a081018252436001600160401b031681528454600160801b900463ffffffff811660208301529091820190610d6e906001600160801b031661ffff86167f0000000000000000000000000000000000000000000000000000000000000002611c6e565b63ffffffff1681526020015f81526020018787604051602001610d929291906128bf565b60405160208183030381529060405280519060200120815250600a5f610dc133855f9182526020526040902090565b815260208082019290925260409081015f2083518154858501519386015163ffffffff908116600160601b0263ffffffff60601b1991909516600160401b026bffffffffffffffffffffffff199092166001600160401b03909316929092171716919091178155606083015160018201556080909201516002909201919091557fbee983fc706c692efb9b0240bddc5666c010a53af55ed5fb42d226e7e4293869903390610e71908a018a61289c565b604080516001600160a01b03909316835263ffffffff90911660208301520160405180910390a150505050505050565b6060610eac826118ac565b6001600160401b03811115610ec357610ec3612984565b604051908082528060200260200182016040528015610eec578160200160208202803683370190505b5090505f5b83811015610f2357610f1b82868684818110610f0f57610f0f612998565b90506020020135611cc6565b600101610ef1565b509392505050565b6060610f42610f3d604084018461291f565b611d1d565b610f79610f52602085018561289c565b600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1760e01b90565b610ff5610f8c6040860160208701612843565b5f65ff000000ff00600883811b91821664ff000000ff9185901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b92915050565b604051602001611007939291906129c3565b6040516020818303038152906040529050919050565b5f848152600a60205260408120805490916001600160401b039091169003611058576040516319a1b6d960e21b815260040160405180910390fd5b80600101545f0361107c576040516378ef3a4760e01b815260040160405180910390fd5b6001546001600160401b0316611095602086018661289c565b63ffffffff16116110b9576040516303d618e560e41b815260040160405180910390fd5b82826040516020016110cc9291906128bf565b60405160208183030381529060405280519060200120816002015414611105576040516333b4605560e11b815260040160405180910390fd5b5050505050565b5f868152600a602052604090208054600160601b900463ffffffff1682811461114857604051630f8b88ed60e11b815260040160405180910390fd5b5f61119d83600101548989808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508a54600160801b90046001600160801b031691508690506115bc565b90505f5b848110156112b557368686838181106111bc576111bc612998565b90506020028101906111ce91906129f6565b90506111f6886111e460a08401608085016128f9565b6060840135610b7a60a086018661291f565b61121357604051637000a9fd60e11b815260040160405180910390fd5b611221838260600135611842565b61123e57604051637000a9fd60e11b815260040160405180910390fd5b61124e60a08201608083016128f9565b6001600160a01b03166112778d6112686020850185612964565b84602001358560400135611886565b6001600160a01b03161461129e57604051638baa579f60e01b815260040160405180910390fd5b6112ac838260600135611e04565b506001016111a1565b5050505050505050505050565b5f805b6112d2604084018461291f565b90508110156113da57610dad60f31b6112ee604085018561291f565b838181106112fe576112fe612998565b90506020028101906113109190612a14565b61131e906020810190612a28565b6001600160f01b031916036113d25761133a604084018461291f565b8281811061134a5761134a612998565b905060200281019061135c9190612a14565b61136a906020810190612a4f565b905060201461138c57604051633efce24360e11b815260040160405180910390fd5b611399604084018461291f565b828181106113a9576113a9612998565b90506020028101906113bb9190612a14565b6113c9906020810190612a4f565b61044091612a91565b6001016112c5565b5060405163484ab7df60e01b815260040160405180910390fd5b606061140c6114066020840184612964565b60f81b90565b61141f610f52604085016020860161289c565b6040840135611437610f8c6080870160608801612843565b61144a610f5260a088016080890161289c565b6040516001600160f81b031990951660208601526001600160e01b0319938416602186015260258501929092526001600160c01b031916604584015216604d82015260a0830135605182015260c08301356071820152609101611007565b5f6101008311156114cc57604051632f43154560e11b815260040160405180910390fd5b845f5b8481101561150a57611500828787848181106114ed576114ed612998565b905060200201358387901c600116611e38565b91506001016114cf565b5090951495945050505050565b60408051808201909152606081525f60208201525f611537601084612ac2565b15611543576001611545565b5f5b60ff16611553601085612ad5565b61155d91906128e6565b90506040518060400160405280826001600160401b0381111561158257611582612984565b6040519080825280602002602001820160405280156115ab578160200160208202803683370190505b508152602001939093525090919050565b60606115c7836118ac565b84511415806115de57506115db84846118f4565b82115b156115fc576040516302fb251f60e51b815260040160405180910390fd5b83516001600160401b0381111561161557611615612984565b60405190808252806020026020018201604052801561163e578160200160208202803683370190505b5090505f805b8382101561169a575f611658888388611e61565b90506116648782611842565b158061167557506116758482611842565b156116835750600101611644565b61168d8482611cc6565b5060019182019101611644565b5050949350505050565b5f826001015482106116c957604051634e23d03560e01b815260040160405180910390fd5b600482901c600f83166116dd816010612ae8565b60ff16855f0183815481106116f4576116f4612998565b905f5260205f200154901c61ffff16925050505b92915050565b5f82820161ffff80851690821610156104405761ffff915050611708565b8260010154821061175057604051634e23d03560e01b815260040160405180910390fd5b600482901c600f83165f611765826010612ae8565b60ff1661ffff901b1990505f82601061177e9190612ae8565b60ff168561ffff16901b90508082885f0186815481106117a0576117a0612998565b905f5260205f2001541617875f0185815481106117bf576117bf612998565b5f9182526020909120015550505050505050565b6040516bffffffffffffffffffffffff19606086901b1660208201525f90819060340160408051808303601f190181529190528051602090910120600188015488549192506118379183908890600160801b90046001600160801b03168888611e84565b979650505050505050565b5f5f600883901c90506118778385838151811061186157611861612998565b6020026020010151611eaf90919063ffffffff16565b60ff1660011491505092915050565b5f5f5f61189587878787611eb9565b915091506118a281611f76565b5095945050505050565b5f6101006118bb8360ff6128e6565b6117089190612ad5565b5f60038211156118f05760036118dc600184612b0b565b6118e69190612ad5565b6117089083612b0b565b5090565b5f81158061190157508251155b1561190d57505f611708565b5f610100830460ff8416825b82811080156119285750865181105b15611abd575f87828151811061194057611940612998565b602002602001015190505f516020612c235f395f51905f52600182901c165f516020612c235f395f51905f5282160190505f516020612bc35f395f51905f52600282901c165f516020612bc35f395f51905f5282160190505f516020612c035f395f51905f52600482901c165f516020612c035f395f51905f5282160190505f516020612c435f395f51905f52600882901c165f516020612c435f395f51905f5282160190505f516020612be35f395f51905f52601082901c165f516020612be35f395f51905f5282160190507bffffffff00000000ffffffff00000000ffffffff00000000ffffffff602082901c167bffffffff00000000ffffffff00000000ffffffff00000000ffffffff821601905077ffffffffffffffff0000000000000000ffffffffffffffff604082901c1677ffffffffffffffff0000000000000000ffffffffffffffff82160190506001600160801b03608082901c166001600160801b0382160190508085019450508080600101915050611919565b505f81118015611acd5750855182105b15611c64575f6001826001901b0390505f81888581518110611af157611af1612998565b60200260200101511690505f516020612c235f395f51905f52600182901c165f516020612c235f395f51905f5282160190505f516020612bc35f395f51905f52600282901c165f516020612bc35f395f51905f5282160190505f516020612c035f395f51905f52600482901c165f516020612c035f395f51905f5282160190505f516020612c435f395f51905f52600882901c165f516020612c435f395f51905f5282160190505f516020612be35f395f51905f52601082901c165f516020612be35f395f51905f5282160190507bffffffff00000000ffffffff00000000ffffffff00000000ffffffff602082901c167bffffffff00000000ffffffff00000000ffffffff00000000ffffffff821601905077ffffffffffffffff0000000000000000ffffffffffffffff604082901c1677ffffffffffffffff0000000000000000ffffffffffffffff82160190506001600160801b03608082901c166001600160801b038216019050808501945050505b5090949350505050565b5f81611c7b8560016120c7565b611c8590826128e6565b9050611c928460016120c7565b611c9d906002612b1e565b611ca89060016128e6565b611cb290826128e6565b90506108a781611cc1876118c5565b612104565b5f600882901c9050611cfa82848381518110611ce457611ce4612998565b602002602001015161211990919063ffffffff16565b838281518110611d0c57611d0c612998565b602002602001018181525050505050565b60605f611d2983612126565b90505f5b83811015610f235781858583818110611d4857611d48612998565b9050602002810190611d5a9190612a14565b611d68906020810190612a28565b611da4878785818110611d7d57611d7d612998565b9050602002810190611d8f9190612a14565b611d9d906020810190612a4f565b9050612126565b878785818110611db657611db6612998565b9050602002810190611dc89190612a14565b611dd6906020810190612a4f565b604051602001611dea959493929190612b35565b60408051601f198184030181529190529150600101611d2d565b5f600882901c9050611cfa82848381518110611e2257611e22612998565b602002602001015161215690919063ffffffff16565b5f818015611e4c57835f5284602052611e54565b845f52836020525b505060405f209392505050565b5f815f03611e7057505f610440565b505f92835260209190915260409091200690565b5f838510611e9357505f611ea5565b611ea08686868686612164565b871490505b9695505050505050565b60ff161c60011690565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611eee57505f90506003611f6d565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611f3f573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116611f67575f60019250925050611f6d565b91505f90505b94509492505050565b5f816004811115611f8957611f89612b71565b03611f915750565b6001816004811115611fa557611fa5612b71565b03611ff75760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b600281600481111561200b5761200b612b71565b036120585760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611fee565b600381600481111561206c5761206c612b71565b036120c45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611fee565b50565b5f5f6120d28461220a565b90506120dd8361229d565b80156120ec575083816001901b105b6120f6575f6120f9565b60015b60ff16019392505050565b5f8183106121125781610440565b5090919050565b600160ff919091161b1790565b606063ffffffff82111561214d57604051637404cccd60e11b815260040160405180910390fd5b611708826122c9565b600160ff919091161b191690565b5f85815b838110156121ff57866001166001148061218457508587600101145b156121bb576121b485858381811061219e5761219e612998565b90506020020135835f9182526020526040902090565b91506121e9565b6121e6828686848181106121d1576121d1612998565b905060200201355f9182526020526040902090565b91505b600196871c965f19909601861c86019501612168565b509695505050505050565b5f80608083901c1561221e57608092831c92015b604083901c1561223057604092831c92015b602083901c1561224257602092831c92015b601083901c1561225457601092831c92015b600883901c1561226657600892831c92015b600483901c1561227857600492831c92015b600283901c1561228a57600292831c92015b600183901c156117085760010192915050565b5f60028260038111156122b2576122b2612b71565b6122bc9190612b85565b60ff166001149050919050565b6060603f8263ffffffff16116122f457604051603f60fa1b60fa84901b166020820152602101611007565b613fff8263ffffffff16116123535761233061231c6403fffffffc600285901b166001612ba6565b600881811b62ffff001691901c60ff161790565b604051602001611007919060f09190911b6001600160f01b031916815260020190565b633fffffff8263ffffffff16116123c5576123a260028363ffffffff16901b600261237e9190612ba6565b600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1790565b604051602001611007919060e09190911b6001600160e01b031916815260040190565b604051600360f81b60208201526001600160e01b0319600884811c62ff00ff1663ff00ff009186901b9190911617601081811c91901b1760e01b166021820152602501611007565b828054828255905f5260205f20908101928215612449575f5260205f209182015b8281111561244957825482559160010191906001019061242e565b506118f092915061248e565b828054828255905f5260205f20908101928215612449579160200282015b82811115612449578251825591602001919060010190612473565b5b808211156118f0575f815560010161248f565b6001600160801b03851681526001600160801b0384166020820152826040820152608060608201525f60c0820183516040608085015281815180845260e0860191506020830193505f92505b8083101561251157835182526020820191506020840193506001830192506124ee565b50602086015160a086015280935050505095945050505050565b5f5f83601f84011261253b575f5ffd5b5081356001600160401b03811115612551575f5ffd5b6020830191508360208260051b850101111561256b575f5ffd5b9250929050565b5f5f5f60408486031215612584575f5ffd5b83356001600160401b03811115612599575f5ffd5b6125a58682870161252b565b909790965060209590950135949350505050565b602080825282518282018190525f918401906040840190835b818110156125f05783518352602093840193909201916001016125d2565b509095945050505050565b5f6060828403121561260b575f5ffd5b50919050565b5f60e0828403121561260b575f5ffd5b5f5f5f5f5f5f5f5f5f6101808a8c03121561263a575f5ffd5b89356001600160401b0381111561264f575f5ffd5b61265b8c828d016125fb565b99505060208a01356001600160401b03811115612676575f5ffd5b6126828c828d0161252b565b90995097505060408a01356001600160401b038111156126a0575f5ffd5b6126ac8c828d0161252b565b90975095506126c090508b60608c01612611565b93506101408a01356001600160401b038111156126db575f5ffd5b6126e78c828d0161252b565b9a9d999c50979a969995989497966101600135949350505050565b5f5f5f60408486031215612714575f5ffd5b8335925060208401356001600160401b03811115612730575f5ffd5b61273c8682870161252b565b9497909650939450505050565b5f5f5f5f6060858703121561275c575f5ffd5b8435935060208501356001600160401b03811115612778575f5ffd5b6127848782880161252b565b9598909750949560400135949350505050565b5f602082840312156127a7575f5ffd5b5035919050565b5f5f5f5f606085870312156127c1575f5ffd5b84356001600160401b038111156127d6575f5ffd5b6127e2878288016125fb565b94505060208501356001600160401b038111156127fd575f5ffd5b6128098782880161252b565b90945092505060408501356001600160401b03811115612827575f5ffd5b850160c08188031215612838575f5ffd5b939692955090935050565b5f60208284031215612853575f5ffd5b81356001600160401b0381168114610440575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160801b03818116838216019081111561170857611708612869565b5f602082840312156128ac575f5ffd5b813563ffffffff81168114610440575f5ffd5b5f6001600160fb1b038311156128d3575f5ffd5b8260051b80858437919091019392505050565b8082018082111561170857611708612869565b5f60208284031215612909575f5ffd5b81356001600160a01b0381168114610440575f5ffd5b5f5f8335601e19843603018112612934575f5ffd5b8301803591506001600160401b0382111561294d575f5ffd5b6020019150600581901b360382131561256b575f5ffd5b5f60208284031215612974575f5ffd5b813560ff81168114610440575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f6129ce82866129ac565b6001600160e01b031994909416845250506001600160c01b0319166004820152600c01919050565b5f823560be19833603018112612a0a575f5ffd5b9190910192915050565b5f8235603e19833603018112612a0a575f5ffd5b5f60208284031215612a38575f5ffd5b81356001600160f01b031981168114610440575f5ffd5b5f5f8335601e19843603018112612a64575f5ffd5b8301803591506001600160401b03821115612a7d575f5ffd5b60200191503681900382131561256b575f5ffd5b80356020831015611708575f19602084900360031b1b1692915050565b634e487b7160e01b5f52601260045260245ffd5b5f82612ad057612ad0612aae565b500690565b5f82612ae357612ae3612aae565b500490565b60ff8181168382160290811690818114612b0457612b04612869565b5092915050565b8181038181111561170857611708612869565b808202811582820484141761170857611708612869565b5f612b4082886129ac565b6001600160f01b031987168152612b5a60028201876129ac565b9050838582375f9301928352509095945050505050565b634e487b7160e01b5f52602160045260245ffd5b5f60ff831680612b9757612b97612aae565b8060ff84160691505092915050565b63ffffffff81811683821601908111156117085761170861286956fe33333333333333333333333333333333333333333333333333333333333333330000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f555555555555555555555555555555555555555555555555555555555555555500ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ffa2646970667358221220bb783e6f87d678903cb96088c2c12d2cac558d531f4f913f330f95e9f12638ce64736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0x697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000200000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000002", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000200000000000000000000000000000001" - } - }, - "45": { - "address": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", - "code": "0x6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063c298557814602a575b5f5ffd5b5f60405190815260200160405180910390f3fea26469706673582212204906941268839d569ecaf7e18f112ade90c540d0de5142ca9f7725e57df91e0964736f6c634300081c00330000000000000000", - "storage": {} - }, - "21": { - "address": "0x0000F90827F1C53a10cb7A02335B175320002935", - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000037": "0x7dba6cfd190cd676ceab572c0ea8a2de9f397df61f588974668e90e365110250", - "0x0000000000000000000000000000000000000000000000000000000000000034": "0x8c4beb67b351b6f576899b2961e2e3f654a8701446181d5bb0c02bf691aac216", - "0x000000000000000000000000000000000000000000000000000000000000003a": "0x3d3679da9629b4cbcf3faf9cd7ae517797ec91b7984eff0a4e3e2a5feec1a077", - "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd98073d4f2271bc16437511a4d4f43553358cb4faeabeaa326aa9e7fd2a343a8", - "0x000000000000000000000000000000000000000000000000000000000000004a": "0x50af6778675a6e30db0584111c11dccc9946048e4ef88a6794a138478fc0087d", - "0x0000000000000000000000000000000000000000000000000000000000000024": "0xdbb108e107182aa903847566da4e97dea7c12849e41d711ff3015e7a9d7e25af", - "0x000000000000000000000000000000000000000000000000000000000000001d": "0xe519dc053717c8dc8dc205a65af318cdbb0e06a8a071f994e5a6bd1a1b3c825e", - "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9cdf7ab6a05c98761f73090b8f8674ed56fd9d53dc13a3e708204d8a4e87372d", - "0x000000000000000000000000000000000000000000000000000000000000002a": "0x6c82fe27742545bd9ab2f22dbbd5dcf3bcaf06da76a88b567b4612b80c341684", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0xc2c67fb618e169cec3b5ecceb5de747ee01f36a775797dd92504163f1fa2eb1a", - "0x0000000000000000000000000000000000000000000000000000000000000012": "0x7a21b4fb1f04fc9ee8ae2b9585f8c5248ee7adb73cad020920b34d72dcf86aa9", - "0x0000000000000000000000000000000000000000000000000000000000000043": "0xdb64fa0b93af4865852cb32ada05816c70990f993d9565df3b806e15af7f1774", - "0x0000000000000000000000000000000000000000000000000000000000000046": "0x4944a97eb3f2cef53621ac688fff89485c821677a6a000cb4c587c7a7cd80a30", - "0x0000000000000000000000000000000000000000000000000000000000000020": "0xb2835abdfda964c75cb55670e70c963f945bd4ffe74453f8053d17108cc477fd", - "0x0000000000000000000000000000000000000000000000000000000000000023": "0xa090d2b60842f14ec13240bd07bf4be2f6d3faac6c0e82d1b6e9e79c91f71ca7", - "0x0000000000000000000000000000000000000000000000000000000000000048": "0x09cdc091ee3d28c27b1d81e24e200a415304990490f712280e7a9f5b7e528077", - "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0c9f4bccf18f5fbe86e1891c3ea5a92f15dc928a7376dfce0aa3ed642d68af1c", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x94d0bab2834f8ad853c6d0fd6bca9a5019ff287f8607d9573cfbbaa44fa9132e", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x508921c105d59853aa52ef7fe87433b1847a5d97d61535e3189abe8aaad908b2", - "0x0000000000000000000000000000000000000000000000000000000000000028": "0x0327ac71308d01e45657fd4d8b343a2d6aeef00f80395f6511416274997cfcfb", - "0x0000000000000000000000000000000000000000000000000000000000000031": "0xd10fc0bcc990f04c1a06a2b1e72bd617a020aa0d4dc89f5f98c21233a492d27a", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x3cb864613b04eae08a873b64b3a67360f98c41ca76abf9d06bbab1e83c59a5f1", - "0x0000000000000000000000000000000000000000000000000000000000000017": "0x3e7878505d2f5b0548009687f85e3e0491e8a193703cbffd103e9060de532e0d", - "0x0000000000000000000000000000000000000000000000000000000000000018": "0x615a70fc83ca07e7b6fb4a9da05b734479fff08ddef45bf3dd0bbeae10410b36", - "0x0000000000000000000000000000000000000000000000000000000000000025": "0x29030d8519c14cc30a1d3613e13a26354214da5cb8e2c750c95d2884cb17d86d", - "0x0000000000000000000000000000000000000000000000000000000000000038": "0x15cef137d4c827121f1fbca673176fc376cad8582b90e695642b3fb913ae5e5f", - "0x000000000000000000000000000000000000000000000000000000000000000e": "0xd9952f05760fda1a4ca998fecf94b6a11c7a1e9ad5c10636e52b58f238948638", - "0x0000000000000000000000000000000000000000000000000000000000000006": "0x1a4d3e4c00a8711d4b79df383d348de72fafd510cde2998cca273bb5e945634e", - "0x0000000000000000000000000000000000000000000000000000000000000021": "0xfe1a914f738a66729c97f9a987f003733572a7032aacc5237ea73e5d1791be15", - "0x0000000000000000000000000000000000000000000000000000000000000040": "0x872e3b28751def5dd02c04d2e37334aecd63ccdf73b529c5002608f179d81726", - "0x0000000000000000000000000000000000000000000000000000000000000014": "0x1bebfec7364d7b14f77a125c75e06f6cb54998cc2344bcb5838e8f4ac34a799d", - "0x0000000000000000000000000000000000000000000000000000000000000041": "0x282828ce280e5c594f5009f451d6b953dd91b234e9a371f2f5dec7d00661baf7", - "0x000000000000000000000000000000000000000000000000000000000000000d": "0x1c1b8f0803eeb1e1c9447df7b8c9e88817463c785e5462357fcebc7f61cc1a0c", - "0x000000000000000000000000000000000000000000000000000000000000001f": "0xdf915f928c9abcae4533730be221820ff4fe7f6d15364411eefc3b4cf5938d3c", - "0x0000000000000000000000000000000000000000000000000000000000000036": "0x5237502c06660666a59cb0f6f943122ef30db0b39702d0e9b18cf75a67df705e", - "0x0000000000000000000000000000000000000000000000000000000000000029": "0x62d466ab11e99482d3b48cb05959ca8068f8894abd45dce90b13c6a95105669f", - "0x000000000000000000000000000000000000000000000000000000000000002b": "0xcbb14f647e27741b02ef0b47727affdd37883853eaf0a80960ed9fe2417d0155", - "0x0000000000000000000000000000000000000000000000000000000000000011": "0xc206586970ef9cceb3ae4113133b749725d48af653dc3e32e9af6d51f1eb2a8c", - "0x000000000000000000000000000000000000000000000000000000000000001c": "0x247e36fad5af4cccc7207545c64b2298a49af78c7c5a01df85143a32b7be3f08", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x7ad4f2b98894e6ba818e2d230abc7d7b8cbf85d936245a24b2a374f6a81b286f", - "0x000000000000000000000000000000000000000000000000000000000000003d": "0x3da9512589d1256bc831a5beb801a7cc63c26b3870aaf0c191e488644d00eaf6", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0xe6bf887ab883f3817f530198a3738495cf7d121a8f2f62ee38c80fc783963b4d", - "0x0000000000000000000000000000000000000000000000000000000000000015": "0xd4a299c088a928b0d78615b35e8b8d464fe3cd0924e1725a2549512915413888", - "0x0000000000000000000000000000000000000000000000000000000000000022": "0xee5607c31047cd8a768e51e8ed47f2d4e00bbec79087a19fcce4122774bad68a", - "0x000000000000000000000000000000000000000000000000000000000000003c": "0x34e05358e6d64f940d16692aae278df9fb79cd5b31b7ca6ed535c97b61c3f169", - "0x0000000000000000000000000000000000000000000000000000000000000016": "0x459aa0106e3ca4cba1215c6e8683b5a567bdf5c99ec02e4452044c8a115e7a00", - "0x000000000000000000000000000000000000000000000000000000000000002f": "0x07e19ac1142916f7b63663fdeb9401d54ab18eb8e7fb3204149b2a20a091b71d", - "0x000000000000000000000000000000000000000000000000000000000000003f": "0x36a957fcb4cfb170e2e9cfce0c40bd287ea53e70b533319b1d086008df464717", - "0x000000000000000000000000000000000000000000000000000000000000000f": "0x1259338c2e8df334b092b9881f8ea7882b3a7c475d1979af0249c8c69ea28114", - "0x000000000000000000000000000000000000000000000000000000000000000c": "0x177dfa3cdf65903c0235fb12887725bcc4148ed51225be84db90e30ff36d7aaf", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x8e1841b9f4c6c6ea52f11ec7783a38eab6993840412f1e63773c3b168c8ee2a4", - "0x0000000000000000000000000000000000000000000000000000000000000044": "0x41c10fdeffe6c9d73e9a769d02b02e2687efd05b4ed27ee30379437589fc7739", - "0x000000000000000000000000000000000000000000000000000000000000002e": "0xe7365b9dcb1a93128cc1671627b2b8fb038bf002a5037066a55ce27c444cf0e4", - "0x000000000000000000000000000000000000000000000000000000000000001b": "0xfcd358887d6cead17a31275c7817f4be8ec2399670152736d8afab9f29857a01", - "0x0000000000000000000000000000000000000000000000000000000000000042": "0x6a8b913bac58f095f9b55cdb2ae9e635686313b60c1a43b187aae0a2d07e0aaa", - "0x0000000000000000000000000000000000000000000000000000000000000008": "0x890b339bb81e6d15de4e50b8abb87abd937eee6d83913a577c5e8eb73a185254", - "0x0000000000000000000000000000000000000000000000000000000000000045": "0xc36a0aa304696f05f336fbc39393d93a6d0cc1cd0431ec9a3b09b2ace2fe4e1d", - "0x0000000000000000000000000000000000000000000000000000000000000027": "0xa0c3168f121ede472d57a4e81a1a8e73c9199affdaaa8ec83797b0ca9e65a84a", - "0x0000000000000000000000000000000000000000000000000000000000000019": "0x01e3a46edccdf8e4fa7ba377876c2caa4e7f20e357a7cd69802c90b0f64cd81c", - "0x000000000000000000000000000000000000000000000000000000000000003b": "0xd98147582c214dceef19d46c0658b3b05d326254c0ef38aa875594495756b8ea", - "0x0000000000000000000000000000000000000000000000000000000000000035": "0xb7b970a400b2c4c7f3322a9573369b865c272b6da5348cb0e032e434b33c06bd", - "0x0000000000000000000000000000000000000000000000000000000000000010": "0x2e461dcac54d9f4f52ba077f666a5ddd431341514db0e9f369dbf5a9ae700546", - "0x000000000000000000000000000000000000000000000000000000000000003e": "0x57530920cd762202e8ee8e2016744727f97449998791effbe34ca75314899fb7", - "0x0000000000000000000000000000000000000000000000000000000000000007": "0xa64333f38cf6f05bf76e867e663294e79156582d738eff8997eaa7b092edead1", - "0x0000000000000000000000000000000000000000000000000000000000000013": "0xc08e55cd55f98b08478d00b19d0fdb5aa012f2ef0bb37db6bace5143a65a4b2e", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0xbf2bc3d6b0df3ed1f839eb7050814edbbc865f4ff3543dda811bf71ea59e41ec", - "0x0000000000000000000000000000000000000000000000000000000000000039": "0xf306e8539937696cdc87c607ed45127cba87fb213a4b0c620506d16908a03e0d", - "0x000000000000000000000000000000000000000000000000000000000000001a": "0x30bc181b20c968c2ea5c4b97b241f0035b237c019218eb8ca93486a439c483ba", - "0x0000000000000000000000000000000000000000000000000000000000000009": "0xa94e1c9553391106e061daab33fcb441afa04f603106d943475777270ccfa64e", - "0x000000000000000000000000000000000000000000000000000000000000001e": "0xa0fc11bb768bcb3b45c699aee78a664e69b3857627b3b1a342ea80f14efb57ab", - "0x000000000000000000000000000000000000000000000000000000000000002d": "0xa7aaf5a2b8a2feab05e51df7035f2eb5d8e32ec6f16c0086a35854e25df98670", - "0x0000000000000000000000000000000000000000000000000000000000000047": "0xd20fca41a076819db29bd1ab62bb5489070d0656896cca9069ba181962219a87", - "0x0000000000000000000000000000000000000000000000000000000000000049": "0x1df27bb7e07a1aad2084ccb75255169ca7d1a3e6737d0308412cb860f538192b", - "0x0000000000000000000000000000000000000000000000000000000000000032": "0x672b80852a0a8f09cc2c2d3c9f40c1c48b88b897fff3f63bd2adc934502a92cf", - "0x000000000000000000000000000000000000000000000000000000000000002c": "0xcc56a05b1bc445067c57c06caea96b020b02d035a9702dbfcd6a0a078be87e92" - } - }, - "37": { - "address": "0xac06641381166cf085281c45292147f833C622d7", - "code": "0x608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f8168881565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c00330000000000", - "storage": {} - }, - "47": { - "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e", - "code": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806346fbf68e1461004e5780638568520614610085578063ce5484281461009a578063eab66d7a146100ad575b5f5ffd5b61007061005c36600461027a565b5f6020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61009861009336600461029a565b6100d8565b005b6100986100a836600461027a565b610111565b6001546100c0906001600160a01b031681565b6040516001600160a01b03909116815260200161007c565b6001546001600160a01b031633146101035760405163794821ff60e01b815260040160405180910390fd5b61010d8282610148565b5050565b6001546001600160a01b0316331461013c5760405163794821ff60e01b815260040160405180910390fd5b610145816101cf565b50565b6001600160a01b03821661016f576040516339b190bb60e11b815260040160405180910390fd5b6001600160a01b0382165f8181526020818152604091829020805460ff19168515159081179091558251938452908301527f65d3a1fd4c13f05cba164f80d03ce90fb4b5e21946bfc3ab7dbd434c2d0b9152910160405180910390a15050565b6001600160a01b0381166101f6576040516339b190bb60e11b815260040160405180910390fd5b600154604080516001600160a01b03928316815291831660208301527f06b4167a2528887a1e97a366eefe8549bfbf1ea3e6ac81cb2564a934d20e8892910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b0381168114610275575f5ffd5b919050565b5f6020828403121561028a575f5ffd5b6102938261025f565b9392505050565b5f5f604083850312156102ab575f5ffd5b6102b48361025f565b9150602083013580151581146102c8575f5ffd5b80915050925092905056fea2646970667358221220d968f6e7b0fa23955f1f9580db081bbf816d7e99d0b3ab6d1bf5c644ea927f8d64736f6c634300081c003300", - "storage": { - "0x723077b8a1b173adc35e5f0e7e3662fd1208212cb629f9c128551ea7168da722": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", - "0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "6": { - "address": "0x0165878A594ca255338adfa4d48449f69242Eb8F", - "code": "0x730165878a594ca255338adfa4d48449f69242eb8f3014608060405260043610610034575f3560e01c8063439fab9114610038575b5f5ffd5b818015610043575f5ffd5b50610057610052366004610683565b610059565b005b5f6100827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b0316036100a8576040516282b42960e81b815260040160405180910390fd5b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab5f6100d584840185610760565b8051835491925090839060ff1916600183818111156100f6576100f6610802565b02179055505f7f03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145f1b60405161012b90610676565b908152602001604051809103905ff08015801561014a573d5f5f3e3d5ffd5b507f03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145f908152600285016020908152604080832080546001600160a01b0319166001600160a01b0386169081179091558151608081018352848152808401859052808301859052606081019190915260018085528089019093529220825181549495509293909291839160ff19169083818111156101ea576101ea610802565b02179055506020828101518254604080860151610100600160881b031990921661010067ffffffffffffffff9485160267ffffffffffffffff60481b191617600160481b9390921692909202178355606093840151600193840180546001600160a01b0319166001600160a01b0392831617905581516080810183525f808252818501819052818401819052918716958101959095526002815287840190925290208251815491929091839160ff199091169083818111156102ae576102ae610802565b021790555060208201518154604080850151610100600160881b031990921661010067ffffffffffffffff9485160267ffffffffffffffff60481b191617600160481b9390921692909202178255606090920151600190910180546001600160a01b0319166001600160a01b03909216919091179055515f907f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b799061035290610676565b908152602001604051809103905ff080158015610371573d5f5f3e3d5ffd5b507f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b795f908152600286016020908152604080832080546001600160a01b0319166001600160a01b038616908117909155815160808101835284815280840185905280830185905260608101919091528151637061726160e01b81850152607d60e31b6024820152825180820360080181526028909101835280519084012084526001808a019093529220825181549495509293909291839160ff191690838181111561043f5761043f610802565b021790555060208201518154604084015167ffffffffffffffff908116600160481b0267ffffffffffffffff60481b19919093166101000216610100600160881b031990911617178155606090910151600190910180546001600160a01b039092166001600160a01b03199092169190911790555f6104db7f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f690565b60408501518155602080860151600180840180546fffffffffffffffffffffffffffffffff19166001600160801b0393841617905560c08801516002909401939093557f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22f80546001600160a01b03969096166001600160c01b031990961695909517607d60a31b1790945560a08601517f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23155606086015160808701518516600160801b02908516177f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c2305560e08601517f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23380546101009889015190961690970270ffffffffffffffffffffffffffffffffff1990951660ff9091161793909317909455505f80527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e9052507f8510b5c501cdfc97210e26067e7b0bee5b5cd43d52d902454bc5e2b62167df1d805460ff19169091179055505050565b61032e8061081783390190565b5f5f60208385031215610694575f5ffd5b823567ffffffffffffffff8111156106aa575f5ffd5b8301601f810185136106ba575f5ffd5b803567ffffffffffffffff8111156106d0575f5ffd5b8560208284010111156106e1575f5ffd5b6020919091019590945092505050565b604051610120810167ffffffffffffffff8111828210171561072157634e487b7160e01b5f52604160045260245ffd5b60405290565b803560028110610735575f5ffd5b919050565b80356001600160801b0381168114610735575f5ffd5b803560ff81168114610735575f5ffd5b5f610120828403128015610772575f5ffd5b5061077b6106f1565b61078483610727565b81526107926020840161073a565b6020820152604083810135908201526107ad6060840161073a565b60608201526107be6080840161073a565b608082015260a0838101359082015260c080840135908201526107e360e08401610750565b60e08201526107f5610100840161073a565b6101008201529392505050565b634e487b7160e01b5f52602160045260245ffdfe60c0604052348015600e575f5ffd5b5060405161032e38038061032e833981016040819052602b916036565b6080523360a052604c565b5f602082840312156045575f5ffd5b5051919050565b60805160a0516102bc6100725f395f81816052015261010d01525f60cf01526102bc5ff3fe608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c0033a264697066735822122048797f739f4990ae363e6737b404ae972b4684803172bd809c64956b6bae7dc264736f6c634300081c003300000000000000", - "storage": {} - }, - "20": { - "address": "0x00000000219ab540356cBB839Cbe05303d7705Fa", - "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033000000000000000000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", - "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", - "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", - "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", - "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", - "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", - "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", - "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", - "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", - "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", - "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", - "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", - "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", - "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", - "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", - "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", - "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", - "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", - "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", - "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7", - "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", - "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", - "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", - "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", - "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", - "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", - "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", - "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", - "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", - "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1" - } - }, - "44": { - "address": "0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf", - "code": "0x60806040526004361061021d575f3560e01c8063805ce31d1161011e578063b39053c5116100a8578063d58a8be41161006d578063d58a8be4146106cb578063df4ed829146106de578063f2e500b2146106fd578063f906d30914610710578063fe61cc491461072f575f5ffd5b8063b39053c5146105f9578063be8d42c014610618578063c536218f1461066e578063c66414c51461068d578063c9bd1e5b146106ac575f5ffd5b806390ffc4f9116100ee57806390ffc4f914610561578063928bc49d14610594578063988062ea146105b357806398ea5fca146105d2578063b0a23d44146105da575f5ffd5b8063805ce31d146104d55780638450a97c146104f7578063860929ee146105165780638ce2e33914610542575f5ffd5b80633ae65d7e116101aa57806346cd27511161016f57806346cd27511461045157806352054834146104705780635c60da1b146104835780635e6dae26146104975780636a64d9fb146104b6575f5ffd5b80633ae65d7e1461038a5780633f8bb4d9146103a9578063423e69b6146103c857806342e3ccfa14610413578063439fab9114610432575f5ffd5b806327c1d325116101f057806327c1d325146102cb5780632a6c3229146102ea5780632dd677b1146103295780632fb8ac581461034857806338004f6914610367575f5ffd5b80630705f4651461022157806309824a80146102565780630b6176461461026b57806326aa101f1461029c575b5f5ffd5b34801561022c575f5ffd5b5061024061023b3660046129ee565b61074e565b60405161024d9190612a19565b60405180910390f35b610269610264366004612a47565b6107c8565b005b348015610276575f5ffd5b5061027f610843565b604080519283526001600160801b0390911660208301520161024d565b3480156102a7575f5ffd5b506102bb6102b6366004612a47565b6108b7565b604051901515815260200161024d565b3480156102d6575f5ffd5b506102696102e5366004612aa6565b610933565b3480156102f5575f5ffd5b506103096103043660046129ee565b6109bb565b604080516001600160401b0393841681529290911660208301520161024d565b348015610334575f5ffd5b50610269610343366004612aa6565b610a39565b348015610353575f5ffd5b50610269610362366004612ae4565b610a91565b348015610372575f5ffd5b505f516020613ae35f395f51905f525460ff16610240565b348015610395575f5ffd5b506102696103a4366004612aa6565b610b3e565b3480156103b4575f5ffd5b506102696103c3366004612aa6565b610bb8565b3480156103d3575f5ffd5b506103fb7f0000000000000000000000000e801d84fa97b50751dbf25036d067dcf18858bf81565b6040516001600160a01b03909116815260200161024d565b34801561041e575f5ffd5b5061026961042d366004612aa6565b610c10565b34801561043d575f5ffd5b5061026961044c366004612aa6565b610c68565b34801561045c575f5ffd5b5061026961046b366004612aa6565b610ca1565b61026961047e366004612b50565b610d1b565b34801561048e575f5ffd5b506103fb610da1565b3480156104a2575f5ffd5b506103fb6104b13660046129ee565b610dcf565b3480156104c1575f5ffd5b506102696104d0366004612ae4565b610dd9565b3480156104e0575f5ffd5b506104e9610e33565b60405190815260200161024d565b348015610502575f5ffd5b50610269610511366004612aa6565b610e9f565b348015610521575f5ffd5b5061052a610f19565b6040516001600160401b03909116815260200161024d565b34801561054d575f5ffd5b5061026961055c366004612c2f565b610f85565b34801561056c575f5ffd5b506103fb7f00000000000000000000000099bba657f2bbc93c02d617f8ba121cb8fc104acf81565b34801561059f575f5ffd5b506104e96105ae366004612ccb565b6110fd565b3480156105be575f5ffd5b506102696105cd366004612aa6565b61119c565b6102696111f4565b3480156105e5575f5ffd5b506102696105f4366004612aa6565b61122e565b348015610604575f5ffd5b506102696106133660046129ee565b611286565b348015610623575f5ffd5b506104e9610632366004612a47565b6001600160a01b03165f9081527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e602052604090206001015490565b348015610679575f5ffd5b50610269610688366004612aa6565b6112e8565b348015610698575f5ffd5b506102bb6106a7366004612d32565b611340565b3480156106b7575f5ffd5b506102696106c6366004612aa6565b611389565b6102696106d9366004612d5b565b6113e1565b3480156106e9575f5ffd5b506102696106f8366004612db4565b611438565b61026961070b366004612e3f565b61191f565b34801561071b575f5ffd5b5061026961072a366004612aa6565b6119ac565b34801561073a575f5ffd5b506103fb6107493660046129ee565b611a04565b604051630705f46560e01b8152600481018290525f9073e7f1725e7734ce288f8367e1bb143e90bb3f051290630705f46590602401602060405180830381865af415801561079e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107c29190612f00565b92915050565b5f5c156107d3575f5ffd5b60015f5d6040516213049560e71b81526001600160a01b038216600482015273e7f1725e7734ce288f8367e1bb143e90bb3f0512906309824a80906024015f6040518083038186803b158015610827575f5ffd5b505af4158015610839573d5f5f3e3d5ffd5b505050505f5f5d50565b5f5f73e7f1725e7734ce288f8367e1bb143e90bb3f0512630b6176466040518163ffffffff1660e01b81526004016040805180830381865af415801561088b573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108af9190612f1e565b915091509091565b6040516326aa101f60e01b81526001600160a01b03821660048201525f9073e7f1725e7734ce288f8367e1bb143e90bb3f0512906326aa101f90602401602060405180830381865af415801561090f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107c29190612f4d565b333014610952576040516282b42960e81b815260040160405180910390fd5b6040516316cba71360e21b815273dc64a140aa3e981100a9beca4e685f962f0cf6c990635b2e9c4c9061098b9085908590600401612f94565b5f6040518083038186803b1580156109a1575f5ffd5b505af41580156109b3573d5f5f3e3d5ffd5b505050505050565b604051632a6c322960e01b8152600481018290525f90819073e7f1725e7734ce288f8367e1bb143e90bb3f051290632a6c3229906024016040805180830381865af4158015610a0c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a309190612fa7565b91509150915091565b333014610a58576040516282b42960e81b815260040160405180910390fd5b604051638257f3d560e01b8152735fc8d32690cc91d4c39d9d3abcbd16989f87570790638257f3d59061098b9085908590600401612f94565b333014610ab0576040516282b42960e81b815260040160405180910390fd5b60405163fe1aa59d60e01b8152735fc8d32690cc91d4c39d9d3abcbd16989f8757079063fe1aa59d90610b0d9086907f0000000000000000000000000e801d84fa97b50751dbf25036d067dcf18858bf9087908790600401612fd4565b5f6040518083038186803b158015610b23575f5ffd5b505af4158015610b35573d5f5f3e3d5ffd5b50505050505050565b333014610b5d576040516282b42960e81b815260040160405180910390fd5b604051636552967560e01b8152735fc8d32690cc91d4c39d9d3abcbd16989f8757079063655296759061098b907f0000000000000000000000000e801d84fa97b50751dbf25036d067dcf18858bf9086908690600401613008565b333014610bd7576040516282b42960e81b815260040160405180910390fd5b604051632539464560e01b815273dc64a140aa3e981100a9beca4e685f962f0cf6c99063253946459061098b9085908590600401612f94565b333014610c2f576040516282b42960e81b815260040160405180910390fd5b6040516315d149b360e31b8152735fc8d32690cc91d4c39d9d3abcbd16989f8757079063ae8a4d989061098b9085908590600401612f94565b60405163439fab9160e01b8152730165878a594ca255338adfa4d48449f69242eb8f9063439fab919061098b9085908590600401612f94565b333014610cc0576040516282b42960e81b815260040160405180910390fd5b604051636552967560e01b815273dc64a140aa3e981100a9beca4e685f962f0cf6c99063655296759061098b907f0000000000000000000000000e801d84fa97b50751dbf25036d067dcf18858bf9086908690600401613008565b5f5c15610d26575f5ffd5b60015f5d6040516326415bf360e21b815273e7f1725e7734ce288f8367e1bb143e90bb3f0512906399056fcc90610d6b9088903390899089908990899060040161306d565b5f6040518083038186803b158015610d81575f5ffd5b505af4158015610d93573d5f5f3e3d5ffd5b505050505f5f5d5050505050565b5f610dca7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905090565b5f6107c282611a78565b333014610df8576040516282b42960e81b815260040160405180910390fd5b604051630e83f5b160e31b815273dc64a140aa3e981100a9beca4e685f962f0cf6c99063741fad8890610b0d90869086908690600401613102565b5f73e7f1725e7734ce288f8367e1bb143e90bb3f051263805ce31d6040518163ffffffff1660e01b8152600401602060405180830381865af4158015610e7b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dca919061311b565b333014610ebe576040516282b42960e81b815260040160405180910390fd5b60405163c31308d160e01b815273dc64a140aa3e981100a9beca4e685f962f0cf6c99063c31308d19061098b907f0000000000000000000000000e801d84fa97b50751dbf25036d067dcf18858bf9086908690600401613008565b5f739fe46736679d2d9a65f0992f2272de9f3c7fa6e063fd10ebe56040518163ffffffff1660e01b8152600401602060405180830381865af4158015610f61573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dca9190613132565b5f5c15610f90575f5ffd5b60015f5d5f516020613ae35f395f51905f52610fe4610fb56040880160208901612d32565b66ffffffffffffff600882901c165f908152600484016020526040902054600160ff9092169190911b16151590565b1561100257604051633ab3447f60e11b815260040160405180910390fd5b6110466110156040880160208901612d32565b66ffffffffffffff600882901c165f90815260048401602052604090208054600160ff9093169290921b9091179055565b5f611052878787611ad0565b905061105e8185611b41565b61107b576040516309bde33960e01b815260040160405180910390fd5b505f61108687611be4565b90506110986040880160208901612d32565b6001600160401b03167f8856ab63954e6c2938803a4654fb704c8779757e7bfdbe94a578e341ec637a95886040013583866040516110e9939291909283529015156020830152604082015260600190565b60405180910390a250505f5f5d5050505050565b60405163928bc49d60e01b81526001600160a01b038416600482015263ffffffff831660248201526001600160801b03821660448201525f9073e7f1725e7734ce288f8367e1bb143e90bb3f05129063928bc49d90606401602060405180830381865af4158015611170573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611194919061311b565b949350505050565b3330146111bb576040516282b42960e81b815260040160405180910390fd5b60405163017b731160e01b8152735fc8d32690cc91d4c39d9d3abcbd16989f8757079063017b73119061098b9085908590600401612f94565b604080513381523460208201527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4910160405180910390a1565b33301461124d576040516282b42960e81b815260040160405180910390fd5b604051630643752360e11b815273dc64a140aa3e981100a9beca4e685f962f0cf6c990630c86ea469061098b9085908590600401612f94565b604051634a283cd960e01b815260048101829052739fe46736679d2d9a65f0992f2272de9f3c7fa6e090634a283cd9906024015f6040518083038186803b1580156112cf575f5ffd5b505af41580156112e1573d5f5f3e3d5ffd5b5050505050565b333014611307576040516282b42960e81b815260040160405180910390fd5b6040516315d149b360e31b815273dc64a140aa3e981100a9beca4e685f962f0cf6c99063ae8a4d989061098b9085908590600401612f94565b66ffffffffffffff600882901c165f9081527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96af6020526040812054600160ff84161b1615156107c2565b3330146113a8576040516282b42960e81b815260040160405180910390fd5b604051638257f3d560e01b815273dc64a140aa3e981100a9beca4e685f962f0cf6c990638257f3d59061098b9085908590600401612f94565b5f5c156113ec575f5ffd5b60015f5d60ff831615611412576040516386eab41b60e01b815260040160405180910390fd5b61142f8460ff8516801561142857611428612a05565b8484611ca1565b5f5f5d50505050565b5f5c15611443575f5ffd5b60015f5d5f5a90505f6114568635611d5a565b80549091506114749061010090046001600160401b03166001613161565b6001600160401b031661148d6040880160208901612d32565b6001600160401b0316146114b457604051633ab3447f60e11b815260040160405180910390fd5b805461010090046001600160401b03168160016114d083613180565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550505f8660405160200161150791906131cc565b6040516020818303038152906040528051906020012090505f61155d8787808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250869250611db0915050565b905061156a81865f611df2565b611587576040516309bde33960e01b815260040160405180910390fd5b5f61159860a08a0160808b01612d32565b6001600160401b031690506115af6127108261327e565b60405a6115bd90603f613291565b6115c791906132a8565b10156115e657604051636eb14fc360e11b815260040160405180910390fd5b60015f6115f960608c0160408d016132c7565b600b81111561160a5761160a612a05565b036116795730638450a97c8361162360608e018e6132e0565b6040518463ffffffff1660e01b8152600401611640929190612f94565b5f604051808303815f88803b158015611657575f5ffd5b5087f193505050508015611669575060015b61167457505f611840565b611840565b600561168b60608c0160408d016132c7565b600b81111561169c5761169c612a05565b036116b5573063c9bd1e5b8361162360608e018e6132e0565b60016116c760608c0160408d016132c7565b600b8111156116d8576116d8612a05565b036116f15730633f8bb4d98361162360608e018e6132e0565b600761170360608c0160408d016132c7565b600b81111561171457611714612a05565b0361172d57306327c1d3258361162360608e018e6132e0565b600861173f60608c0160408d016132c7565b600b81111561175057611750612a05565b03611769573063b0a23d448361162360608e018e6132e0565b600961177b60608c0160408d016132c7565b600b81111561178c5761178c612a05565b036117a557306346cd27518361162360608e018e6132e0565b600a6117b760608c0160408d016132c7565b600b8111156117c8576117c8612a05565b036117e1573063c536218f8361162360608e018e6132e0565b600b6117f360608c0160408d016132c7565b600b81111561180457611804612a05565b0361183d5730636a64d9fb838c3561181f60608f018f6132e0565b6040518563ffffffff1660e01b815260040161164093929190613102565b505f5b5f5a61184c9088613322565b611854611e97565b61185e919061327e565b90505f61186f3a8d60a00135611ebb565b6118799083613291565b90505f61189361188d60c08f01358461327e565b47611ebb565b905061189d611ed0565b8111156118ae576118ae3382611edd565b8c60e001358d5f01357f617fdb0cb78f01551a192a3673208ec5eb09f20a90acf673c63a0dcb11745a7a8f60200160208101906118eb9190612d32565b604080516001600160401b03909216825288151560208301520160405180910390a35050505050505050505f5f5d50505050565b5f5c1561192a575f5ffd5b60015f5d604051631fccb47160e31b8152739fe46736679d2d9a65f0992f2272de9f3c7fa6e09063fe65a38890611973908b908b908b908b908b908b908b908b90600401613335565b5f6040518083038186803b158015611989575f5ffd5b505af415801561199b573d5f5f3e3d5ffd5b505050505f5f5d5050505050505050565b3330146119cb576040516282b42960e81b815260040160405180910390fd5b604051632539464560e01b8152735fc8d32690cc91d4c39d9d3abcbd16989f8757079063253946459061098b9085908590600401612f94565b60405163fe61cc4960e01b8152600481018290525f9073e7f1725e7734ce288f8367e1bb143e90bb3f05129063fe61cc4990602401602060405180830381865af4158015611a54573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107c291906133ef565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b031680611acb5760405163d3227c9b60e01b815260040160405180910390fd5b919050565b5f5f84604051602001611ae3919061346b565b604051602081830303815290604052805190602001209050611b388484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250859250611db0915050565b95945050505050565b6040516372dd6c6d60e11b81525f90735fbdb2315678afecb367f032d93f642f64180aa39063e5bad8da90611b9e907f00000000000000000000000099bba657f2bbc93c02d617f8ba121cb8fc104acf9087908790600401613605565b602060405180830381865af4158015611bb9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bdd9190612f4d565b9392505050565b5f6001815b611bf6606085018561366f565b9050811015611c9a57611c38611c0f606086018661366f565b83818110611c1f57611c1f6136b4565b9050602002810190611c3191906136c8565b8535611f0b565b611c9257611c4c6040850160208601612d32565b6001600160401b03167fa6dc208277bb3da3666e7305baf550db2daf26f8f386a431a4b27cc7a02965a282604051611c8691815260200190565b60405180910390a25f91505b600101611be9565b5092915050565b6001600160801b03341115611cc9576040516330e972ad60e01b815260040160405180910390fd5b611cd381836136e6565b6001600160801b0316341015611cfc5760405163044044a560e21b815260040160405180910390fd5b5f611d078585612127565b9050611d12856121c7565b604080515f808252602082019092526112e19130918491611d43565b6060815260200190600190039081611d2e5790505b5060405180602001604052805f8152508787612271565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ac6020526040902060018101546001600160a01b0316611acb57604051636ddd9da960e01b815260040160405180910390fd5b5f81815b8451811015611dea57611de082868381518110611dd357611dd36136b4565b602002602001015161250c565b9150600101611db4565b509392505050565b6040516316db930b60e11b81525f90738a791620dd6260079bf849dc5567adc3f2fdc31890632db7261690611e58907f00000000000000000000000099bba657f2bbc93c02d617f8ba121cb8fc104acf9061ea0360f01b9089908990899060040161374a565b602060405180830381865af4158015611e73573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111949190612f4d565b5f611ea436610bb8611ebb565b611eaf906010613291565b610dca90618b7261327e565b5f818310611ec95781611bdd565b5090919050565b5f610dca3a615208613291565b5f5f5f5f5f85875af1905080611f0657604051633d2cec6f60e21b815260040160405180910390fd5b505050565b5f615dc0611f1f6040850160208601612d32565b6001600160401b0316611f32919061327e565b60405a611f4090603f613291565b611f4a91906132a8565b1015611f69576040516360ee124760e01b815260040160405180910390fd5b5f611f7760208501856138ef565b60ff1603612001573063f906d309611f956040860160208701612d32565b6001600160401b0316611fab60408701876132e0565b6040518463ffffffff1660e01b8152600401611fc8929190612f94565b5f604051808303815f88803b158015611fdf575f5ffd5b5087f193505050508015611ff1575060015b611ffc57505f6107c2565b61211e565b600161201060208501856138ef565b60ff160361202e5730632dd677b1611f956040860160208701612d32565b600261203d60208501856138ef565b60ff160361205b5730633ae65d7e611f956040860160208701612d32565b600361206a60208501856138ef565b60ff160361208857306342e3ccfa611f956040860160208701612d32565b600461209760208501856138ef565b60ff16036120b5573063988062ea611f956040860160208701612d32565b60056120c460208501856138ef565b60ff16036121175730632fb8ac586120e26040860160208701612d32565b6001600160401b0316846120f960408801886132e0565b6040518563ffffffff1660e01b8152600401611fc893929190613102565b505f6107c2565b50600192915050565b604080518082019091525f8152606060208201526040518060400160405280600160ff1681526020016040518060400160405280866001600160a01b03168152602001855f81111561217b5761217b612a05565b60ff1690526040516121ae919060200181516001600160a01b0316815260209182015160ff169181019190915260400190565b60408051601f1981840301815291905290529392505050565b6121d9816001600160a01b0316612538565b6121f65760405163c1ab6dc160e01b815260040160405180910390fd5b6001600160a01b0381165f9081527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e60208190526040909120805460ff16801561224457506122448161257e565b1561226257604051633ea7ffd960e11b815260040160405180910390fd5b805460ff191660011790555050565b612279612592565b6001600160801b033411156122a1576040516330e972ad60e01b815260040160405180910390fd5b6122ab81836136e6565b6001600160801b03163410156122d45760405163044044a560e21b815260040160405180910390fd5b5f6122fe7f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79611a78565b90506123136001600160a01b03821634611edd565b8451600810156123365760405163df8153c760e01b815260040160405180910390fd5b5f85516001600160401b0381111561235057612350613705565b60405190808252806020026020018201604052801561239557816020015b604080518082019091525f81526060602082015281526020019060019003908161236e5790505b5090505f5b86518110156123ea576123c58782815181106123b8576123b86136b4565b60200260200101516125d9565b8282815181106123d7576123d76136b4565b602090810291909101015260010161239a565b507e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96b0545f516020613ae35f395f51905f529061242f906001600160401b03166001613161565b816005015f6101000a8154816001600160401b0302191690836001600160401b031602179055505f6040518060e001604052808b6001600160a01b031681526020018481526020018a8152602001888152602001868834612490919061390a565b61249a919061390a565b6001600160801b03908116825288811660208301528716604091820152600584015490519192507f550e2067494b1736ea5573f2d19cdc0ac95b410fff161bf16f11c6229655ec9c916124f8916001600160401b0316908490613978565b60405180910390a150505050505050505050565b5f818310612526575f828152602084905260409020611bdd565b5f838152602083905260409020611bdd565b5f6001600160a01b0382163f158015906107c25750506001600160a01b03163f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470141590565b5f61258b82600101541590565b1592915050565b5f516020613ae35f395f51905f5280545f9060ff1660018111156125b8576125b8612a05565b146125d657604051633ac4266d60e11b815260040160405180910390fd5b50565b604080518082019091525f815260606020820152602082015160ff165f819003612622575f5f848060200190518101906126139190613a8d565b9250925050611b38828261263b565b604051636448d6e960e11b815260040160405180910390fd5b604080518082019091525f8152606060208201525f7f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e6001600160a01b0385165f90815260208290526040902080549192509060ff166126ae5760405163259ba1ad60e01b815260040160405180910390fd5b5f846001600160801b0316116126d75760405163162908e360e11b815260040160405180910390fd5b600181015461270d5760018201546126fa906001600160a01b03168633876127a5565b6127048585612821565b925050506107c2565b6127168161257e565b1561278c57604051632770a7eb60e21b81523360048201526001600160801b03851660248201526001600160a01b03861690639dc29fac906044015f604051808303815f87803b158015612768575f5ffd5b505af115801561277a573d5f5f3e3d5ffd5b50505050612704816001015485612888565b604051636890662960e01b815260040160405180910390fd5b6127b7836001600160a01b0316612538565b6127d45760405163c1ab6dc160e01b815260040160405180910390fd5b806001600160801b03165f036127fd5760405163162908e360e11b815260040160405180910390fd5b61281b6001600160a01b03841683866001600160801b0385166128e2565b50505050565b604080518082019091525f8152606060208201526040805180820182525f8152815180830183526001600160a01b0386168082526001600160801b0380871660209384019081528551808501939093525116938101939093529091908201906060016121ae565b6040805180820182525f8152606060208083018290528351808501855260018152845180860186528781526001600160801b0387811691840191825286518085018a905291511695810195909552929390830191016121ae565b6040516001600160a01b038085166024830152831660448201526064810182905261281b90859060840160408051601f198184030181529190526020810180516001600160e01b03166323b872dd60e01b1790525f5f836001600160a01b0316836040516129509190613acc565b5f604051808303815f865af19150503d805f8114612989576040519150601f19603f3d011682016040523d82523d5f602084013e61298e565b606091505b50915091505f8280156129b95750815115806129b95750818060200190518101906129b99190612f4d565b90508015806129d057506001600160a01b0385163b155b156112e15760405163022e258160e11b815260040160405180910390fd5b5f602082840312156129fe575f5ffd5b5035919050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310612a2d57612a2d612a05565b91905290565b6001600160a01b03811681146125d6575f5ffd5b5f60208284031215612a57575f5ffd5b8135611bdd81612a33565b5f5f83601f840112612a72575f5ffd5b5081356001600160401b03811115612a88575f5ffd5b602083019150836020828501011115612a9f575f5ffd5b9250929050565b5f5f60208385031215612ab7575f5ffd5b82356001600160401b03811115612acc575f5ffd5b612ad885828601612a62565b90969095509350505050565b5f5f5f60408486031215612af6575f5ffd5b8335925060208401356001600160401b03811115612b12575f5ffd5b612b1e86828701612a62565b9497909650939450505050565b63ffffffff811681146125d6575f5ffd5b6001600160801b03811681146125d6575f5ffd5b5f5f5f5f5f60a08688031215612b64575f5ffd5b8535612b6f81612a33565b94506020860135612b7f81612b2b565b935060408601356001600160401b03811115612b99575f5ffd5b860160408189031215612baa575f5ffd5b92506060860135612bba81612b3c565b91506080860135612bca81612b3c565b809150509295509295909350565b5f5f83601f840112612be8575f5ffd5b5081356001600160401b03811115612bfe575f5ffd5b6020830191508360208260051b8501011115612a9f575f5ffd5b5f6101008284031215612c29575f5ffd5b50919050565b5f5f5f5f5f60808688031215612c43575f5ffd5b85356001600160401b03811115612c58575f5ffd5b860160808189031215612c69575f5ffd5b945060208601356001600160401b03811115612c83575f5ffd5b612c8f88828901612bd8565b90955093505060408601356001600160401b03811115612cad575f5ffd5b612cb988828901612c18565b95989497509295606001359392505050565b5f5f5f60608486031215612cdd575f5ffd5b8335612ce881612a33565b92506020840135612cf881612b2b565b91506040840135612d0881612b3c565b809150509250925092565b6001600160401b03811681146125d6575f5ffd5b8035611acb81612d13565b5f60208284031215612d42575f5ffd5b8135611bdd81612d13565b60ff811681146125d6575f5ffd5b5f5f5f5f60808587031215612d6e575f5ffd5b8435612d7981612a33565b93506020850135612d8981612d4d565b92506040850135612d9981612b3c565b91506060850135612da981612b3c565b939692955090935050565b5f5f5f5f60608587031215612dc7575f5ffd5b84356001600160401b03811115612ddc575f5ffd5b612de887828801612c18565b94505060208501356001600160401b03811115612e03575f5ffd5b612e0f87828801612bd8565b90945092505060408501356001600160401b03811115612e2d575f5ffd5b85016101408188031215612da9575f5ffd5b5f5f5f5f5f5f5f5f60a0898b031215612e56575f5ffd5b88356001600160401b03811115612e6b575f5ffd5b612e778b828c01612a62565b90995097505060208901356001600160401b03811115612e95575f5ffd5b612ea18b828c01612bd8565b90975095505060408901356001600160401b03811115612ebf575f5ffd5b612ecb8b828c01612a62565b9095509350506060890135612edf81612b3c565b91506080890135612eef81612b3c565b809150509295985092959890939650565b5f60208284031215612f10575f5ffd5b815160028110611bdd575f5ffd5b5f5f60408385031215612f2f575f5ffd5b82516020840151909250612f4281612b3c565b809150509250929050565b5f60208284031215612f5d575f5ffd5b81518015158114611bdd575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f611194602083018486612f6c565b5f5f60408385031215612fb8575f5ffd5b8251612fc381612d13565b6020840151909250612f4281612d13565b8481526001600160a01b03841660208201526060604082018190525f90612ffe9083018486612f6c565b9695505050505050565b6001600160a01b03841681526040602082018190525f90611b389083018486612f6c565b5f5f8335601e19843603018112613041575f5ffd5b83016020810192503590506001600160401b0381111561305f575f5ffd5b803603821315612a9f575f5ffd5b6001600160a01b0387811682528616602082015263ffffffff8516604082015260c060608201525f8435600381108015906130a6575f5ffd5b5060c08301526130b9602086018661302c565b604060e08501526130cf61010085018284612f6c565b925050506001600160801b03841660808301526130f760a08301846001600160801b03169052565b979650505050505050565b838152604060208201525f611b38604083018486612f6c565b5f6020828403121561312b575f5ffd5b5051919050565b5f60208284031215613142575f5ffd5b8151611bdd81612d13565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908111156107c2576107c261314d565b5f6001600160401b0382166001600160401b0381036131a1576131a161314d565b60010192915050565b8035600c8110611acb575f5ffd5b600c81106131c8576131c8612a05565b9052565b60208082528235828201525f908301356131e581612d13565b6001600160401b038116604084015250613201604084016131aa565b61320e60608401826131b8565b5061321c606084018461302c565b610100608085015261323361012085018284612f6c565b91505061324260808501612d27565b6001600160401b03811660a08501525060a084013560c08481019190915284013560e08085019190915290930135610100909201919091525090565b808201808211156107c2576107c261314d565b80820281158282048414176107c2576107c261314d565b5f826132c257634e487b7160e01b5f52601260045260245ffd5b500490565b5f602082840312156132d7575f5ffd5b611bdd826131aa565b5f5f8335601e198436030181126132f5575f5ffd5b8301803591506001600160401b0382111561330e575f5ffd5b602001915036819003821315612a9f575f5ffd5b818103818111156107c2576107c261314d565b60a081525f61334860a083018a8c612f6c565b82810360208401528088825260208201905060208960051b8301018a5f5b8b8110156133a457848303601f19018452613381828e61302c565b61338c858284612f6c565b60209687019690955093909301925050600101613366565b505084810360408601526133b981898b612f6c565b93505050506133d360608301856001600160801b03169052565b6001600160801b03831660808301529998505050505050505050565b5f602082840312156133ff575f5ffd5b8151611bdd81612a33565b5f5f8335601e1984360301811261341f575f5ffd5b83016020810192503590506001600160401b0381111561343d575f5ffd5b8060051b3603821315612a9f575f5ffd5b5f8235605e19833603018112613462575f5ffd5b90910192915050565b60208082528235828201525f9060a083019084013561348981612d13565b6001600160401b0381166040850152505f60408501359050806060850152506134b5606085018561340a565b6080808601528281845260c08601905060c08260051b8701019350825f5b838110156135555787860360bf190183526134ee828661344e565b80356134f981612d4d565b60ff168752602081013561350c81612d13565b6001600160401b03166020880152613527604082018261302c565b91506060604089015261353e606089018383612f6c565b9750505060209283019291909101906001016134d3565b5093979650505050505050565b803561356d81612d4d565b60ff168252602081013561358081612b2b565b63ffffffff1660208301526040818101359083015260608101356135a381612d13565b6001600160401b0316606083015260808101356135bf81612b2b565b63ffffffff16608083015260a090810135910152565b8183525f6001600160fb1b038311156135ec575f5ffd5b8260051b80836020870137939093016020019392505050565b6001600160a01b03841681526020810183905260606040820181905261362d90820183613562565b5f61363b60c084018461340a565b610100610120850152613653610160850182846135d5565b60e0959095013561014094909401939093525091949350505050565b5f5f8335601e19843603018112613684575f5ffd5b8301803591506001600160401b0382111561369d575f5ffd5b6020019150600581901b3603821315612a9f575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f8235605e198336030181126136dc575f5ffd5b9190910192915050565b6001600160801b0381811683821601908111156107c2576107c261314d565b634e487b7160e01b5f52604160045260245ffd5b80358252602080820135908301525f613735604083018361340a565b60606040860152611b386060860182846135d5565b6001600160a01b03861681526001600160e01b0319851660208201526040810184905260a060608201525f833536859003609e19018112613789575f5ffd5b61014060a0840152840180356101e084015260208101356102008401526040810135610220840152606081013561024084015261028083016137ce608083018361340a565b925060a0610260860152818383526102a0860190506102a08460051b8701019250815f5b8581101561386e5787850361029f1901835261380e828561344e565b8035865260208101356001600160e01b0319811680821461382d575f5ffd5b602088015250613840604082018261302c565b915060606040880152613857606088018383612f6c565b9650505060209283019291909101906001016137f2565b5050505061387f602087018761344e565b848203609f190160c086015291506138978183613719565b9150506138aa60e0840160408701613562565b6138b861010086018661340a565b848303609f19016101a08601526138d08382846135d5565b6101208801356101c087015286151560808701529350612ffe92505050565b5f602082840312156138ff575f5ffd5b8135611bdd81612d4d565b6001600160801b0382811682821603908111156107c2576107c261314d565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff81511682525f6020820151604060208501526111946040850182613929565b6001600160401b0383168152604060208201525f610120820160018060a01b038451166040840152602084015160e06060850152818151808452610140860191506101408160051b87010193506020830192505f5b818110156139ff5761013f198786030183526139ea858551613957565b945060209384019392909201916001016139cd565b505050506040840151838203603f19016080850152613a1e8282613957565b9150506060840151603f198483030160a0850152613a3c8282613929565b9150506080840151613a5960c08501826001600160801b03169052565b5060a08401516001600160801b03811660e08501525060c08401516001600160801b03811661010085015250949350505050565b5f5f5f60608486031215613a9f575f5ffd5b8351613aaa81612d4d565b6020850151909350613abb81612a33565b6040850151909250612d0881612b3c565b5f82518060208501845e5f92019182525091905056fe0096e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96aba2646970667358221220d2f603e4644996fdd6f5bfe996a433ec4c63b91e433ec6617ddd8c10790babb164736f6c634300081c003300000000000000000000000000", - "storage": {} - }, - "11": { - "address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", - "code": "0x739fe46736679d2d9a65f0992f2272de9f3c7fa6e03014608060405260043610610055575f3560e01c80634a283cd91461005957806376b1d08f1461007a578063fd10ebe514610099578063fe65a388146100d2575b5f5ffd5b818015610064575f5ffd5b50610078610073366004610aed565b6100f1565b005b610082600881565b60405160ff90911681526020015b60405180910390f35b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96b0546040516001600160401b039091168152602001610090565b8180156100dd575f5ffd5b506100786100ec366004610b67565b610202565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020547e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab906001600160a01b0316806101e4578260405161015990610ae0565b908152602001604051809103905ff080158015610178573d5f5f3e3d5ffd5b505f84815260028401602090815260409182902080546001600160a01b0319166001600160a01b0385169081179091558251878152918201529192507f7c96960a1ebd8cc753b10836ea25bd7c9c4f8cd43590db1e8b3648cb0ec4cc89910160405180910390a1505050565b604051630d82532d60e21b815260040160405180910390fd5b505050565b61028d336102448a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061029792505050565b61024e888a610c98565b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508992508891506102bf9050565b5050505050505050565b6040805180820182525f80825260606020928301528251808401909352825281019190915290565b6102c761056c565b6001600160801b033411156102ef576040516330e972ad60e01b815260040160405180910390fd5b6102f98183610d8e565b6001600160801b03163410156103225760405163044044a560e21b815260040160405180910390fd5b5f61034c7f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b796105c5565b90506103616001600160a01b0382163461061d565b8451600810156103845760405163df8153c760e01b815260040160405180910390fd5b5f85516001600160401b0381111561039e5761039e610c54565b6040519080825280602002602001820160405280156103e357816020015b604080518082019091525f8152606060208201528152602001906001900390816103bc5790505b5090505f5b86518110156104385761041387828151811061040657610406610dad565b6020026020010151610646565b82828151811061042557610425610dad565b60209081029190910101526001016103e8565b507e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96b0547e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab9061048f906001600160401b03166001610dc1565b816005015f6101000a8154816001600160401b0302191690836001600160401b031602179055505f6040518060e001604052808b6001600160a01b031681526020018481526020018a81526020018881526020018688346104f09190610de0565b6104fa9190610de0565b6001600160801b03908116825288811660208301528716604091820152600584015490519192507f550e2067494b1736ea5573f2d19cdc0ac95b410fff161bf16f11c6229655ec9c91610558916001600160401b0316908490610e56565b60405180910390a150505050505050505050565b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab80545f9060ff1660018111156105a4576105a4610f6b565b146105c257604051633ac4266d60e11b815260040160405180910390fd5b50565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b0316806106185760405163d3227c9b60e01b815260040160405180910390fd5b919050565b5f5f5f5f5f85875af19050806101fd57604051633d2cec6f60e21b815260040160405180910390fd5b604080518082019091525f815260606020820152602082015160ff165f819003610698575f5f848060200190518101906106809190610f7f565b925092505061068f82826106b1565b95945050505050565b604051636448d6e960e11b815260040160405180910390fd5b604080518082019091525f8152606060208201525f7f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e6001600160a01b0385165f90815260208290526040902080549192509060ff166107245760405163259ba1ad60e01b815260040160405180910390fd5b5f846001600160801b03161161074d5760405163162908e360e11b815260040160405180910390fd5b6001810154610783576001820154610770906001600160a01b0316863387610821565b61077a858561089d565b9250505061081b565b61078c81610919565b1561080257604051632770a7eb60e21b81523360048201526001600160801b03851660248201526001600160a01b03861690639dc29fac906044015f604051808303815f87803b1580156107de575f5ffd5b505af11580156107f0573d5f5f3e3d5ffd5b5050505061077a81600101548561092d565b604051636890662960e01b815260040160405180910390fd5b92915050565b610833836001600160a01b0316610987565b6108505760405163c1ab6dc160e01b815260040160405180910390fd5b806001600160801b03165f036108795760405163162908e360e11b815260040160405180910390fd5b6108976001600160a01b03841683866001600160801b0385166109cd565b50505050565b604080518082019091525f8152606060208201526040805180820182525f8152815180830183526001600160a01b0386168082526001600160801b0380871660209384019081528551808501939093525116938101939093529091908201906060015b60408051601f1981840301815291905290529392505050565b5f61092682600101541590565b1592915050565b6040805180820182525f8152606060208083018290528351808501855260018152845180860186528781526001600160801b0387811691840191825286518085018a90529151169581019590955292939083019101610900565b5f6001600160a01b0382163f1580159061081b5750506001600160a01b03163f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470141590565b6040516001600160a01b038085166024830152831660448201526064810182905261089790859060840160408051601f198184030181529190526020810180516001600160e01b03166323b872dd60e01b1790525f5f836001600160a01b031683604051610a3b9190610fd9565b5f604051808303815f865af19150503d805f8114610a74576040519150601f19603f3d011682016040523d82523d5f602084013e610a79565b606091505b50915091505f828015610aa4575081511580610aa4575081806020019051810190610aa49190610fef565b9050801580610abb57506001600160a01b0385163b155b15610ad95760405163022e258160e11b815260040160405180910390fd5b5050505050565b61032e8061101683390190565b5f60208284031215610afd575f5ffd5b5035919050565b5f5f83601f840112610b14575f5ffd5b5081356001600160401b03811115610b2a575f5ffd5b602083019150836020828501011115610b41575f5ffd5b9250929050565b6001600160801b03811681146105c2575f5ffd5b803561061881610b48565b5f5f5f5f5f5f5f5f60a0898b031215610b7e575f5ffd5b88356001600160401b03811115610b93575f5ffd5b610b9f8b828c01610b04565b90995097505060208901356001600160401b03811115610bbd575f5ffd5b8901601f81018b13610bcd575f5ffd5b80356001600160401b03811115610be2575f5ffd5b8b60208260051b8401011115610bf6575f5ffd5b6020919091019650945060408901356001600160401b03811115610c18575f5ffd5b610c248b828c01610b04565b9095509350610c37905060608a01610b5c565b9150610c4560808a01610b5c565b90509295985092959890939650565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715610c9057610c90610c54565b604052919050565b5f6001600160401b03831115610cb057610cb0610c54565b8260051b610cc060208201610c68565b84815290830190602081019036831115610cd8575f5ffd5b845b83811015610d705780356001600160401b03811115610cf7575f5ffd5b860136601f820112610d07575f5ffd5b80356001600160401b03811115610d2057610d20610c54565b610d33601f8201601f1916602001610c68565b818152366020838501011115610d47575f5ffd5b816020840160208301375f60208383010152808652505050602083019250602081019050610cda565b5095945050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b03818116838216019081111561081b5761081b610d7a565b634e487b7160e01b5f52603260045260245ffd5b6001600160401b03818116838216019081111561081b5761081b610d7a565b6001600160801b03828116828216039081111561081b5761081b610d7a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff81511682525f602082015160406020850152610e4e6040850182610dff565b949350505050565b6001600160401b0383168152604060208201525f610120820160018060a01b038451166040840152602084015160e06060850152818151808452610140860191506101408160051b87010193506020830192505f5b81811015610edd5761013f19878603018352610ec8858551610e2d565b94506020938401939290920191600101610eab565b505050506040840151838203603f19016080850152610efc8282610e2d565b9150506060840151603f198483030160a0850152610f1a8282610dff565b9150506080840151610f3760c08501826001600160801b03169052565b5060a08401516001600160801b03811660e08501525060c08401516001600160801b03811661010085015250949350505050565b634e487b7160e01b5f52602160045260245ffd5b5f5f5f60608486031215610f91575f5ffd5b835160ff81168114610fa1575f5ffd5b60208501519093506001600160a01b0381168114610fbd575f5ffd5b6040850151909250610fce81610b48565b809150509250925092565b5f82518060208501845e5f920191825250919050565b5f60208284031215610fff575f5ffd5b8151801515811461100e575f5ffd5b939250505056fe60c0604052348015600e575f5ffd5b5060405161032e38038061032e833981016040819052602b916036565b6080523360a052604c565b5f602082840312156045575f5ffd5b5051919050565b60805160a0516102bc6100725f395f81816052015261010d01525f60cf01526102bc5ff3fe608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c0033a2646970667358221220d6b7192f32171e73f3ca8608f2cb38bc543e4d751099308262bcc0a34560c16464736f6c634300081c003300", - "storage": {} - }, - "30": { - "address": "0x809d550fca64d94Bd9F66E60752A544199cfAC3D", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000067": "0x0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000036c02da8a0983159322a80ffe9f24b1acff8b570", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x000000000000000000000000976ea74026e726554db657fa54763abd0c3a0aa9", - "0x0000000000000000000000000000000000000000000000000000000000000065": "0x00000000000000000000000014dc79964da2c08b23698b3d3cc7ca32193d9955", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - }, - "23": { - "address": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", - "code": "0x6080604052600436106101f1575f3560e01c8063886f119511610108578063a6a509be1161009d578063f2fde38b1161006d578063f2fde38b1461062e578063f5d4fed31461064d578063f6848d2414610662578063fabc1cbc1461069b578063fe243a17146106ba575f5ffd5b8063a6a509be1461059c578063cd6dc687146105b1578063d48e8894146105d0578063ea4d3c9b146105fb575f5ffd5b80639ba06275116100d85780639ba062751461050b578063a1ca780b1461053f578063a38406a31461055e578063a3d75e091461057d575f5ffd5b8063886f1195146104815780638da5cb5b146104b45780639104c319146104d15780639b4e4634146104f8575f5ffd5b8063595c6a67116101895780635c975abb116101595780635c975abb146103e9578063715018a614610407578063724af4231461041b57806374cdd7981461043a57806384d810621461046d575f5ffd5b8063595c6a6714610358578063595edbcb1461036c5780635a26fbf41461038b5780635ac86ab7146103aa575f5ffd5b80632eae418c116101c45780632eae418c146102c55780633fb99ca5146102e457806350ff72251461030357806354fd4d5014610337575f5ffd5b80630d1e9de1146101f5578063136439dd146102165780632704351a14610235578063292b7b2b1461027a575b5f5ffd5b348015610200575f5ffd5b5061021461020f366004611d7e565b6106d9565b005b348015610221575f5ffd5b50610214610230366004611d99565b610736565b348015610240575f5ffd5b50609f5461025c90600160a01b900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b348015610285575f5ffd5b506102ad7f0000000000000000000000004ed7c70f96b99c776995fb64377f0d4ab3b0e1c181565b6040516001600160a01b039091168152602001610271565b3480156102d0575f5ffd5b506102146102df366004611db0565b610770565b3480156102ef575f5ffd5b506102146102fe366004611dfe565b6109c9565b34801561030e575f5ffd5b5061032261031d366004611e48565b610a6d565b60408051928352602083019190915201610271565b348015610342575f5ffd5b5061034b610b1d565b6040516102719190611e86565b348015610363575f5ffd5b50610214610b4d565b348015610377575f5ffd5b50609f546102ad906001600160a01b031681565b348015610396575f5ffd5b506102146103a5366004611ebb565b610b61565b3480156103b5575f5ffd5b506103d96103c4366004611ee2565b606654600160ff9092169190911b9081161490565b6040519015158152602001610271565b3480156103f4575f5ffd5b506066545b604051908152602001610271565b348015610412575f5ffd5b50610214610be8565b348015610426575f5ffd5b506103f9610435366004611e48565b610bf9565b348015610445575f5ffd5b506102ad7f000000000000000000000000c7f2cf4845c6db0e1a1e91ed41bcd0fcc1b0e14181565b348015610478575f5ffd5b506102ad610d3e565b34801561048c575f5ffd5b506102ad7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b3480156104bf575f5ffd5b506033546001600160a01b03166102ad565b3480156104dc575f5ffd5b506102ad73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b610214610506366004611f40565b610da1565b348015610516575f5ffd5b506102ad610525366004611d7e565b60986020525f90815260409020546001600160a01b031681565b34801561054a575f5ffd5b50610214610559366004611fb3565b610e52565b348015610569575f5ffd5b506102ad610578366004611d7e565b611073565b348015610588575f5ffd5b5061025c610597366004611d7e565b611144565b3480156105a7575f5ffd5b506103f960995481565b3480156105bc575f5ffd5b506102146105cb366004611fe5565b6111a4565b3480156105db575f5ffd5b506103f96105ea366004611d7e565b609b6020525f908152604090205481565b348015610606575f5ffd5b506102ad7f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b348015610639575f5ffd5b50610214610648366004611d7e565b6112c0565b348015610658575f5ffd5b506103f9609e5481565b34801561066d575f5ffd5b506103d961067c366004611d7e565b6001600160a01b039081165f9081526098602052604090205416151590565b3480156106a6575f5ffd5b506102146106b5366004611d99565b611339565b3480156106c5575f5ffd5b506103f96106d436600461200f565b6113a6565b6106e1611426565b609f80546001600160a01b0319166001600160a01b0383169081179091556040519081527f7025c71a9fe60d709e71b377dc5f7c72c3e1d8539f8022574254e736ceca01e5906020015b60405180910390a150565b61073e611480565b60665481811681146107635760405163c61dca5d60e01b815260040160405180910390fd5b61076c82611523565b5050565b336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8216146107b95760405163f739589b60e01b815260040160405180910390fd5b6107c1611560565b6001600160a01b03831673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0146107fe57604051632711b74d60e11b815260040160405180910390fd5b6001600160a01b038416610825576040516339b190bb60e11b815260040160405180910390fd5b5f81136108455760405163ef147de160e01b815260040160405180910390fd5b6001600160a01b0384165f908152609b602052604081205490829082121561093f575f6108718361205a565b90505f8185111561088f5750806108888186612074565b9250610895565b505f9150835b5f6108a08286612087565b6001600160a01b038a165f818152609b60205260409081902083905551919250907f4e2b791dedccd9fb30141b088cabf5c14a8912b52f59375c95c010700b8c6193906108f09085815260200190565b60405180910390a2886001600160a01b03167fd4def76d6d2bed6f14d5cd9af73cc2913d618d00edde42432e81c09bfe0770988260405161093391815260200190565b60405180910390a25050505b80156109b7576001600160a01b038681165f81815260986020526040908190205490516362483a2160e11b81526004810192909252602482018490529091169063c4907442906044015b5f604051808303815f87803b1580156109a0575f5ffd5b505af11580156109b2573d5f5f3e3d5ffd5b505050505b50506109c3600160c955565b50505050565b336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821614610a125760405163f739589b60e01b815260040160405180910390fd5b610a1a611560565b80609e5f828254610a2b91906120ae565b90915550506040518181527f1ed04b7fd262c0d9e50fa02957f32a81a151f03baaa367faeedc7521b001c4a49060200160405180910390a16109c3600160c955565b5f80336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821614610ab85760405163f739589b60e01b815260040160405180910390fd5b610ac0611560565b6001600160a01b03841673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac014610afd57604051632711b74d60e11b815260040160405180910390fd5b610b0785846115b9565b91509150610b15600160c955565b935093915050565b6060610b487f76312e302e300000000000000000000000000000000000000000000000000006611700565b905090565b610b55611480565b610b5f5f19611523565b565b609f546001600160a01b03163314610b8c57604051630986113760e41b815260040160405180910390fd5b609f805467ffffffffffffffff60a01b1916600160a01b67ffffffffffffffff8416908102919091179091556040519081527f1bc8f042a52db3a437620dea4548f2031fb2a16dd8d3b0b854295528dd2cdd339060200161072b565b610bf0611426565b610b5f5f61173d565b5f336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821614610c435760405163f739589b60e01b815260040160405180910390fd5b610c4b611560565b6001600160a01b03831673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac014610c8857604051632711b74d60e11b815260040160405180910390fd5b5f610c928361178e565b6001600160a01b0386165f908152609b6020526040902054610cb491906120c1565b90505f811215610cd75760405163ef147de160e01b815260040160405180910390fd5b6001600160a01b0385165f818152609b602052604090819020839055517fd4def76d6d2bed6f14d5cd9af73cc2913d618d00edde42432e81c09bfe07709890610d239084815260200190565b60405180910390a29050610d37600160c955565b9392505050565b5f5f610d49816117f7565b610d51611560565b335f908152609860205260409020546001600160a01b031615610d875760405163031a852160e21b815260040160405180910390fd5b5f610d90611822565b925050610d9d600160c955565b5090565b5f610dab816117f7565b610db3611560565b335f908152609860205260409020546001600160a01b031680610ddb57610dd8611822565b90505b6040516326d3918d60e21b81526001600160a01b03821690639b4e4634903490610e11908b908b908b908b908b9060040161210f565b5f604051808303818588803b158015610e28575f5ffd5b505af1158015610e3a573d5f5f3e3d5ffd5b505050505050610e4a600160c955565b505050505050565b6001600160a01b038084165f908152609860205260409020548491163314610e8d576040516312e16d7160e11b815260040160405180910390fd5b610e95611560565b6001600160a01b038416610ebc576040516339b190bb60e11b815260040160405180910390fd5b610eca633b9aca008361215c565b15610ee8576040516347d072bb60e11b815260040160405180910390fd5b6001600160a01b0384165f908152609b602052604081205490811215610f2157604051634b692bcf60e01b815260040160405180910390fd5b5f831315610fe2575f5f610f3587866115b9565b604051631e328e7960e11b81526001600160a01b038a8116600483015273beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0602483015260448201849052606482018390529294509092507f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8290911690633c651cf2906084015f604051808303815f87803b158015610fc5575f5ffd5b505af1158015610fd7573d5f5f3e3d5ffd5b505050505050611068565b5f831215611068575f610ffe8686610ff98761205a565b61197d565b60405163305068e760e11b81526001600160a01b0388811660048301526024820185905267ffffffffffffffff831660448301529192507f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd82909116906360a0d1ce90606401610989565b506109c3600160c955565b6001600160a01b038082165f908152609860205260408120549091168061113e5761113b836001600160a01b03165f1b60405180610940016040528061090e815260200161222161090e9139604080516001600160a01b037f0000000000000000000000004ed7c70f96b99c776995fb64377f0d4ab3b0e1c1166020820152808201919091525f606082015260800160408051601f19818403018152908290526111209291602001612192565b60405160208183030381529060405280519060200120611a76565b90505b92915050565b6001600160a01b0381165f908152609d6020908152604080832081518083019092525460ff8116151580835261010090910467ffffffffffffffff16928201929092529061119a57670de0b6b3a7640000610d37565b6020015192915050565b5f54610100900460ff16158080156111c257505f54600160ff909116105b806111db5750303b1580156111db57505f5460ff166001145b6112435760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015611264575f805461ff0019166101001790555b61126d8361173d565b61127682611523565b80156112bb575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6112c8611426565b6001600160a01b03811661132d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161123a565b6113368161173d565b50565b611341611a82565b606654801982198116146113685760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b5f6001600160a01b03821673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0146113e457604051632711b74d60e11b815260040160405180910390fd5b6001600160a01b0383165f908152609b60205260408120541261141e576001600160a01b0383165f908152609b602052604090205461113b565b505f92915050565b6033546001600160a01b03163314610b5f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161123a565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa1580156114e2573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150691906121ae565b610b5f57604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b600260c954036115b25760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161123a565b600260c955565b5f806001600160a01b0384166115e2576040516339b190bb60e11b815260040160405180910390fd5b5f8312156116035760405163ef147de160e01b815260040160405180910390fd5b6001600160a01b0384165f908152609b602052604081205484916116278383612087565b6001600160a01b0388165f818152609b60205260409081902083905551919250907f4e2b791dedccd9fb30141b088cabf5c14a8912b52f59375c95c010700b8c6193906116779086815260200190565b60405180910390a2866001600160a01b03167fd4def76d6d2bed6f14d5cd9af73cc2913d618d00edde42432e81c09bfe077098826040516116ba91815260200190565b60405180910390a25f81136116d7575f5f945094505050506116f9565b5f8212156116ec575f945092506116f9915050565b5092508391506116f99050565b9250929050565b60605f61170c83611b33565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f6001600160ff1b03821115610d9d5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b606482015260840161123a565b606654600160ff83161b908116036113365760405163840a48d560e01b815260040160405180910390fd5b5f60995f8154611831906121cd565b9091555060408051610940810190915261090e8082525f916118ce91839133916122216020830139604080516001600160a01b037f0000000000000000000000004ed7c70f96b99c776995fb64377f0d4ab3b0e1c1166020820152808201919091525f606082015260800160408051601f19818403018152908290526118ba9291602001612192565b604051602081830303815290604052611b5a565b60405163189acdbd60e31b81523360048201529091506001600160a01b0382169063c4d66de8906024015f604051808303815f87803b15801561190f575f5ffd5b505af1158015611921573d5f5f3e3d5ffd5b5050335f8181526098602052604080822080546001600160a01b0319166001600160a01b038816908117909155905192945092507f21c99d0db02213c32fff5b05cf0a718ab5f858802b91498f80d82270289d856a91a3919050565b5f806119898385612074565b90505f61199586611144565b90505f6119ad67ffffffffffffffff83168488611c5c565b90505f6119ba82846121e5565b6040805180820182526001815267ffffffffffffffff85811660208084018281526001600160a01b038f165f818152609d845287902095518654925168ffffffffffffffffff1990931690151568ffffffffffffffff001916176101009286169290920291909117909455845193845291881691830191909152918101919091529091507fb160ab8589bf47dc04ea11b50d46678d21590cea2ed3e454e7bd3e41510f98cf9060600160405180910390a1979650505050505050565b5f61113b838330611d41565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ade573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b029190612205565b6001600160a01b0316336001600160a01b031614610b5f5760405163794821ff60e01b815260040160405180910390fd5b5f60ff8216601f81111561113e57604051632cd44ac360e21b815260040160405180910390fd5b5f83471015611bab5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e6365000000604482015260640161123a565b81515f03611bfb5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f604482015260640161123a565b8282516020840186f590506001600160a01b038116610d375760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f7900000000000000604482015260640161123a565b5f80805f19858709858702925082811083820303915050805f03611c9357838281611c8957611c89612148565b0492505050610d37565b808411611cda5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b604482015260640161123a565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b6001600160a01b0381168114611336575f5ffd5b5f60208284031215611d8e575f5ffd5b8135610d3781611d6a565b5f60208284031215611da9575f5ffd5b5035919050565b5f5f5f5f60808587031215611dc3575f5ffd5b8435611dce81611d6a565b93506020850135611dde81611d6a565b92506040850135611dee81611d6a565b9396929550929360600135925050565b5f5f5f5f84860360a0811215611e12575f5ffd5b6040811215611e1f575f5ffd5b50849350604084013592506060840135611e3881611d6a565b9396929550929360800135925050565b5f5f5f60608486031215611e5a575f5ffd5b8335611e6581611d6a565b92506020840135611e7581611d6a565b929592945050506040919091013590565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215611ecb575f5ffd5b813567ffffffffffffffff81168114610d37575f5ffd5b5f60208284031215611ef2575f5ffd5b813560ff81168114610d37575f5ffd5b5f5f83601f840112611f12575f5ffd5b50813567ffffffffffffffff811115611f29575f5ffd5b6020830191508360208285010111156116f9575f5ffd5b5f5f5f5f5f60608688031215611f54575f5ffd5b853567ffffffffffffffff811115611f6a575f5ffd5b611f7688828901611f02565b909650945050602086013567ffffffffffffffff811115611f95575f5ffd5b611fa188828901611f02565b96999598509660400135949350505050565b5f5f5f60608486031215611fc5575f5ffd5b8335611fd081611d6a565b95602085013595506040909401359392505050565b5f5f60408385031215611ff6575f5ffd5b823561200181611d6a565b946020939093013593505050565b5f5f60408385031215612020575f5ffd5b823561202b81611d6a565b9150602083013561203b81611d6a565b809150509250929050565b634e487b7160e01b5f52601160045260245ffd5b5f600160ff1b820161206e5761206e612046565b505f0390565b8181038181111561113e5761113e612046565b8082018281125f8312801582168215821617156120a6576120a6612046565b505092915050565b8082018082111561113e5761113e612046565b8181035f8312801583831316838312821617156120e0576120e0612046565b5092915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b606081525f6121226060830187896120e7565b82810360208401526121358186886120e7565b9150508260408301529695505050505050565b634e487b7160e01b5f52601260045260245ffd5b5f8261217657634e487b7160e01b5f52601260045260245ffd5b500790565b5f81518060208401855e5f93019283525090919050565b5f6121a66121a0838661217b565b8461217b565b949350505050565b5f602082840312156121be575f5ffd5b81518015158114610d37575f5ffd5b5f600182016121de576121de612046565b5060010190565b67ffffffffffffffff828116828216039081111561113e5761113e612046565b5f60208284031215612215575f5ffd5b8151610d3781611d6a56fe608060405260405161090e38038061090e83398101604081905261002291610460565b61002e82826000610035565b505061058a565b61003e83610100565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a260008251118061007f5750805b156100fb576100f9836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100e99190610520565b836102a360201b6100291760201c565b505b505050565b610113816102cf60201b6100551760201c565b6101725760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b60648201526084015b60405180910390fd5b6101e6816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d79190610520565b6102cf60201b6100551760201c565b61024b5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610169565b806102827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5060001b6102de60201b6100641760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606102c883836040518060600160405280602781526020016108e7602791396102e1565b9392505050565b6001600160a01b03163b151590565b90565b6060600080856001600160a01b0316856040516102fe919061053b565b600060405180830381855af49150503d8060008114610339576040519150601f19603f3d011682016040523d82523d6000602084013e61033e565b606091505b5090925090506103508683838761035a565b9695505050505050565b606083156103c65782516103bf576001600160a01b0385163b6103bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610169565b50816103d0565b6103d083836103d8565b949350505050565b8151156103e85781518083602001fd5b8060405162461bcd60e51b81526004016101699190610557565b80516001600160a01b038116811461041957600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561044f578181015183820152602001610437565b838111156100f95750506000910152565b6000806040838503121561047357600080fd5b61047c83610402565b60208401519092506001600160401b038082111561049957600080fd5b818501915085601f8301126104ad57600080fd5b8151818111156104bf576104bf61041e565b604051601f8201601f19908116603f011681019083821181831017156104e7576104e761041e565b8160405282815288602084870101111561050057600080fd5b610511836020830160208801610434565b80955050505050509250929050565b60006020828403121561053257600080fd5b6102c882610402565b6000825161054d818460208701610434565b9190910192915050565b6020815260008251806020840152610576816040850160208701610434565b601f01601f19169190910160400192915050565b61034e806105996000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610067565b610100565b565b606061004e83836040518060600160405280602781526020016102f260279139610124565b9392505050565b6001600160a01b03163b151590565b90565b600061009a7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100fb9190610249565b905090565b3660008037600080366000845af43d6000803e80801561011f573d6000f35b3d6000fd5b6060600080856001600160a01b03168560405161014191906102a2565b600060405180830381855af49150503d806000811461017c576040519150601f19603f3d011682016040523d82523d6000602084013e610181565b606091505b50915091506101928683838761019c565b9695505050505050565b6060831561020d578251610206576001600160a01b0385163b6102065760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610217565b610217838361021f565b949350505050565b81511561022f5781518083602001fd5b8060405162461bcd60e51b81526004016101fd91906102be565b60006020828403121561025b57600080fd5b81516001600160a01b038116811461004e57600080fd5b60005b8381101561028d578181015183820152602001610275565b8381111561029c576000848401525b50505050565b600082516102b4818460208701610272565b9190910192915050565b60208152600082518060208401526102dd816040850160208701610272565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d51e81d3bc5ed20a26aeb05dce7e825c503b2061aa78628027300c8d65b9d89a64736f6c634300080c0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220fe49c3bbb4c8ae3857e9da2c037ca93049f5f5931a49706e5b29c897d23875e264736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "35": { - "address": "0x9d4454B023096f34B160D6B654540c56A1F81688", - "code": "0x608060405260043610610021575f3560e01c8063439fab911461008a5761003f565b3661003f5760405163858d70bd60e01b815260040160405180910390fd5b5f6100687f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050365f5f375f5f365f845af43d5f5f3e808015610084573d5ff35b3d5ffd5b005b348015610095575f5ffd5b506100886100a43660046100bc565b6040516282b42960e81b815260040160405180910390fd5b5f5f602083850312156100cd575f5ffd5b823567ffffffffffffffff8111156100e3575f5ffd5b8301601f810185136100f3575f5ffd5b803567ffffffffffffffff811115610109575f5ffd5b85602082840101111561011a575f5ffd5b602091909101959094509250505056fea264697066735822122042eb79be1c5c1bf83d453ef1bcf09a68daefc0a952ec517c315a6e1a8ca586e264736f6c634300081c003300", - "storage": { - "0x24c230e7f96dea56c14d16c737ac85f999d444fd74b5f3f00170ca4640c77b8f": "0x000000000000000000000000beaafda2e17fc95e69dc06878039d274e0d2b21a", - "0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22f": "0x0000000000000000000003e8df077f5f72071df6e8b0a78071e496ba17b5ee0c", - "0x626b8e6b0a06114fed7a662a5b224ce123b32b155eef2616324caf5d9adeb4fa": "0x000000000000000000000000beaafda2e17fc95e69dc06878039d274e0d2b21a", - "0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c233": "0x0000000000000000000000000000000000000000000000000000000000000112", - "0x91839d9989408fbab863f2059ae80fee5216f58ec04fa3bffb021275bf7d4f24": "0x000000000000000000000000df077f5f72071df6e8b0a78071e496ba17b5ee0c", - "0x173ec3ea915b0ecad49b752ec145e745446de67d464520dc696504b3980fccda": "0x000000000000000000000000ac06641381166cf085281c45292147f833c622d7", - "0x59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f7": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x8510b5c501cdfc97210e26067e7b0bee5b5cd43d52d902454bc5e2b62167df1d": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000008f86403a4de0bb5791fa46b8e795c547942fe4cf", - "0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c231": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c230": "0x0000000000000000000000000000000100000000000000000000000000000001", - "0x59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f8": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f6": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x6bd2118f0148c813209325d23233ce0b7f1042ab160c97a1c605fdedff377204": "0x000000000000000000000000df077f5f72071df6e8b0a78071e496ba17b5ee0c", - "0xdf92d0c198eb2c08351629e12172b863967bc505b5d2fa9fdf58f7b97e45495f": "0x000000000000000000000000beaafda2e17fc95e69dc06878039d274e0d2b21a" - } - }, "0": { "address": "0x00000961Ef480Eb55e80D19ad83579A64c007002", "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd00", - "storage": {} - }, - "42": { - "address": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", - "code": "0x608060405234801561000f575f5ffd5b5060043610610148575f3560e01c80637a8b2637116100bf578063ce7c2ac211610079578063ce7c2ac2146102d7578063d9caed12146102ea578063e3dae51c146102fd578063f3e7387514610310578063fabc1cbc14610323578063fdc371ce14610336575f5ffd5b80637a8b26371461025c578063886f11951461026f5780638c871019146102965780638f6a6240146102a9578063ab5921e1146102bc578063c4d66de8146102c4575f5ffd5b8063485cc95511610110578063485cc955146101e257806354fd4d50146101f5578063553ca5f81461020a578063595c6a671461021d5780635ac86ab7146102255780635c975abb14610254575f5ffd5b8063136439dd1461014c5780632495a5991461016157806339b70e38146101915780633a98ef39146101b857806347e7ef24146101cf575b5f5ffd5b61015f61015a3660046111cb565b610349565b005b603254610174906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101747f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b6101c160335481565b604051908152602001610188565b6101c16101dd3660046111f6565b610383565b61015f6101f0366004611220565b6104b2565b6101fd61059d565b6040516101889190611257565b6101c161021836600461128c565b6105cd565b61015f6105e0565b6102446102333660046112bc565b6001805460ff9092161b9081161490565b6040519015158152602001610188565b6001546101c1565b6101c161026a3660046111cb565b6105f4565b6101747f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6101c16102a43660046111cb565b61063d565b6101c16102b736600461128c565b610647565b6101fd610654565b61015f6102d236600461128c565b610674565b6101c16102e536600461128c565b61073a565b6101c16102f83660046112d7565b6107cc565b6101c161030b3660046111cb565b6108ce565b6101c161031e3660046111cb565b610905565b61015f6103313660046111cb565b61090f565b606454610174906001600160a01b031681565b61035161097c565b60015481811681146103765760405163c61dca5d60e01b815260040160405180910390fd5b61037f82610a1f565b5050565b5f5f61038e81610a5c565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750816146103d7576040516348da714f60e01b815260040160405180910390fd5b6103e18484610a92565b6033545f6103f16103e883611329565b90505f6103e86103ff610b4b565b6104099190611329565b90505f610416878361133c565b905080610423848961134f565b61042d9190611366565b9550855f0361044f57604051630c392ed360e11b815260040160405180910390fd5b6104598685611329565b60338190556f4b3b4ca85a86c47a098a223fffffffff101561048e57604051632f14e8a360e11b815260040160405180910390fd5b6104a7826103e86033546104a29190611329565b610bb5565b505050505092915050565b5f54610100900460ff16158080156104d057505f54600160ff909116105b806104e95750303b1580156104e957505f5460ff166001145b61050e5760405162461bcd60e51b815260040161050590611385565b60405180910390fd5b5f805460ff19166001179055801561052f575f805461ff0019166101001790555b606480546001600160a01b0319166001600160a01b03851617905561055382610c01565b8015610598575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60606105c87f76312e302e300000000000000000000000000000000000000000000000000006610d4c565b905090565b5f6105da61026a8361073a565b92915050565b6105e861097c565b6105f25f19610a1f565b565b5f5f6103e86033546106069190611329565b90505f6103e8610614610b4b565b61061e9190611329565b90508161062b858361134f565b6106359190611366565b949350505050565b5f6105da826108ce565b5f6105da61031e8361073a565b60606040518060800160405280604d8152602001611456604d9139905090565b5f54610100900460ff161580801561069257505f54600160ff909116105b806106ab5750303b1580156106ab57505f5460ff166001145b6106c75760405162461bcd60e51b815260040161050590611385565b5f805460ff1916600117905580156106e8575f805461ff0019166101001790555b6106f182610c01565b801561037f575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15050565b60405163fe243a1760e01b81526001600160a01b0382811660048301523060248301525f917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075089091169063fe243a1790604401602060405180830381865afa1580156107a8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105da91906113d3565b5f60016107d881610a5c565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075081614610821576040516348da714f60e01b815260040160405180910390fd5b61082c858585610d89565b6033548084111561085057604051630b469df360e41b815260040160405180910390fd5b5f61085d6103e883611329565b90505f6103e861086b610b4b565b6108759190611329565b905081610882878361134f565b61088c9190611366565b9450610898868461133c565b6033556108b86108a8868361133c565b6103e86033546104a29190611329565b6108c3888887610dcf565b505050509392505050565b5f5f6103e86033546108e09190611329565b90505f6103e86108ee610b4b565b6108f89190611329565b90508061062b838661134f565b5f6105da826105f4565b610917610ec8565b6001548019821981161461093e5760405163c61dca5d60e01b815260040160405180910390fd5b600182905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa1580156109de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0291906113ea565b6105f257604051631d77d47760e21b815260040160405180910390fd5b600181905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b610a71816001805460ff9092161b9081161490565b15610a8f5760405163840a48d560e01b815260040160405180910390fd5b50565b6032546001600160a01b0383811691161480610abb57506064546001600160a01b038381169116145b610ad857604051630312abdd60e61b815260040160405180910390fd5b6064546001600160a01b039081169083160361037f57606454604051636f074d1f60e11b8152600481018390526001600160a01b039091169063de0e9a3e906024015f604051808303815f87803b158015610b31575f5ffd5b505af1158015610b43573d5f5f3e3d5ffd5b505050505050565b6032546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610b91573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c891906113d3565b7fd2494f3479e5da49d386657c292c610b5b01df313d07c62eb0cfa49924a31be881610be984670de0b6b3a764000061134f565b610bf39190611366565b60405190815260200161072e565b5f54610100900460ff16610c6b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610505565b603280546001600160a01b0319166001600160a01b038316179055610c8f5f610a1f565b7f1c540707b00eb5427b6b774fc799d756516a54aee108b64b327acc55af55750760325f9054906101000a90046001600160a01b0316826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d01573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d259190611409565b604080516001600160a01b03909316835260ff90911660208301520160405180910390a150565b60605f610d5883610f79565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b6032546001600160a01b0383811691161480610db257506064546001600160a01b038381169116145b61059857604051630312abdd60e61b815260040160405180910390fd5b6064546001600160a01b0390811690831603610eb45760325460405163095ea7b360e01b81526001600160a01b038481166004830152602482018490529091169063095ea7b3906044016020604051808303815f875af1158015610e35573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e5991906113ea565b50606454604051630ea598cb60e41b8152600481018390526001600160a01b039091169063ea598cb0906024015f604051808303815f87803b158015610e9d575f5ffd5b505af1158015610eaf573d5f5f3e3d5ffd5b505050505b6105986001600160a01b0383168483610fa0565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f24573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f489190611424565b6001600160a01b0316336001600160a01b0316146105f25760405163794821ff60e01b815260040160405180910390fd5b5f60ff8216601f8111156105da57604051632cd44ac360e21b815260040160405180910390fd5b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180516001600160e01b031663a9059cbb60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152610598928692915f9161102f9185169084906110ae565b905080515f148061104f57508080602001905181019061104f91906113ea565b6105985760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610505565b606061063584845f85855f5f866001600160a01b031685876040516110d3919061143f565b5f6040518083038185875af1925050503d805f811461110d576040519150601f19603f3d011682016040523d82523d5f602084013e611112565b606091505b50915091506111238783838761112e565b979650505050505050565b6060831561119c5782515f03611195576001600160a01b0385163b6111955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610505565b5081610635565b61063583838151156111b15781518083602001fd5b8060405162461bcd60e51b81526004016105059190611257565b5f602082840312156111db575f5ffd5b5035919050565b6001600160a01b0381168114610a8f575f5ffd5b5f5f60408385031215611207575f5ffd5b8235611212816111e2565b946020939093013593505050565b5f5f60408385031215611231575f5ffd5b823561123c816111e2565b9150602083013561124c816111e2565b809150509250929050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f6020828403121561129c575f5ffd5b81356112a7816111e2565b9392505050565b60ff81168114610a8f575f5ffd5b5f602082840312156112cc575f5ffd5b81356112a7816112ae565b5f5f5f606084860312156112e9575f5ffd5b83356112f4816111e2565b92506020840135611304816111e2565b929592945050506040919091013590565b634e487b7160e01b5f52601160045260245ffd5b808201808211156105da576105da611315565b818103818111156105da576105da611315565b80820281158282048414176105da576105da611315565b5f8261138057634e487b7160e01b5f52601260045260245ffd5b500490565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b5f602082840312156113e3575f5ffd5b5051919050565b5f602082840312156113fa575f5ffd5b815180151581146112a7575f5ffd5b5f60208284031215611419575f5ffd5b81516112a7816112ae565b5f60208284031215611434575f5ffd5b81516112a7816111e2565b5f82518060208501845e5f92019182525091905056fe4261736520537472617465677920696d706c656d656e746174696f6e20746f20696e68657269742066726f6d20666f72206d6f726520636f6d706c657820696d706c656d656e746174696f6e73a26469706673582212201363f1045faa90db6b9cd5e104a6adf153d8d9848b22c7129cad8df16e32d4e364736f6c634300081c00330000", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" + "0x0000000000000000000000000000000000000000000000000000000000000000": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" } }, - "46": { - "address": "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02", - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", - "storage": { - "0x000000000000000000000000000000000000000000000000000000000000047d": "0x00000000000000000000000000000000000000000000000000000000697238d1", - "0x0000000000000000000000000000000000000000000000000000000000002478": "0x33f4b7a22c274a253f8f047e28aa095a56cd6a25fc20519286f01d7152f92cac", - "0x0000000000000000000000000000000000000000000000000000000000002479": "0x541fa6279d8389cb5710c10254e6d1161fa1764cf808266ae9760c247b1de184", - "0x0000000000000000000000000000000000000000000000000000000000000461": "0x00000000000000000000000000000000000000000000000000000000697238b5", - "0x000000000000000000000000000000000000000000000000000000000000046f": "0x00000000000000000000000000000000000000000000000000000000697238c3", - "0x0000000000000000000000000000000000000000000000000000000000000452": "0x00000000000000000000000000000000000000000000000000000000697238a6", - "0x0000000000000000000000000000000000000000000000000000000000000488": "0x00000000000000000000000000000000000000000000000000000000697238dc", - "0x0000000000000000000000000000000000000000000000000000000000002455": "0x78bb46a7cb61e6bdb34415590d3bec9407a926362a32f794b020948af31eec4b", - "0x0000000000000000000000000000000000000000000000000000000000002487": "0xf98717faec1f38dc071ea8afde5cac7be731a7bbbfb5610c3d306105b58f7492", - "0x0000000000000000000000000000000000000000000000000000000000002482": "0x37388147728cccc62f6c585fd5bd722e8d5579937f466782b716a335f2a04b5a", - "0x0000000000000000000000000000000000000000000000000000000000000472": "0x00000000000000000000000000000000000000000000000000000000697238c6", - "0x0000000000000000000000000000000000000000000000000000000000000464": "0x00000000000000000000000000000000000000000000000000000000697238b8", - "0x0000000000000000000000000000000000000000000000000000000000000445": "0x0000000000000000000000000000000000000000000000000000000069723899", - "0x000000000000000000000000000000000000000000000000000000000000045a": "0x00000000000000000000000000000000000000000000000000000000697238ae", - "0x000000000000000000000000000000000000000000000000000000000000047b": "0x00000000000000000000000000000000000000000000000000000000697238cf", - "0x0000000000000000000000000000000000000000000000000000000000002448": "0xbc6d08fab0741414058297acbf125161f2fdc3e5cb4b0e89d22a188e0c62d2bc", - "0x0000000000000000000000000000000000000000000000000000000000002459": "0x928833d6bb105e2c08853e1399cada4682e4d311c5fa59df0217d934caab7022", - "0x0000000000000000000000000000000000000000000000000000000000002469": "0x5cfddd9a87e0e4ec7bc6e94d00e5c5be95e656a711801aaf3c064e2a56a9fa11", - "0x0000000000000000000000000000000000000000000000000000000000000486": "0x00000000000000000000000000000000000000000000000000000000697238da", - "0x000000000000000000000000000000000000000000000000000000000000244f": "0x180c3597be125112738bcedf70245e215065ef429e8050833554ed7cd2a38804", - "0x000000000000000000000000000000000000000000000000000000000000048c": "0x00000000000000000000000000000000000000000000000000000000697238e0", - "0x0000000000000000000000000000000000000000000000000000000000000477": "0x00000000000000000000000000000000000000000000000000000000697238cb", - "0x0000000000000000000000000000000000000000000000000000000000000456": "0x00000000000000000000000000000000000000000000000000000000697238aa", - "0x000000000000000000000000000000000000000000000000000000000000046c": "0x00000000000000000000000000000000000000000000000000000000697238c0", - "0x0000000000000000000000000000000000000000000000000000000000002453": "0x66d4ea81c801cbd7fce5e6bdf29badadbae8960b164700a48974ca984f6fca28", - "0x000000000000000000000000000000000000000000000000000000000000246c": "0x0bfd9de6fab35b9664efe10d59fcea1a4b19f005627243935f6a52005759b3c1", - "0x0000000000000000000000000000000000000000000000000000000000002474": "0x3a6c344872b8b6a315149265e28ab9b0ada9ea14b9c213ad25f43788a073760f", - "0x0000000000000000000000000000000000000000000000000000000000002476": "0x6bf71b631c30d9491721b446104222470add3e9ecd9f6a761e0cc6f74ae697e3", - "0x0000000000000000000000000000000000000000000000000000000000002481": "0x7781d8ec936c1d1c871b0552c5e39493bda7c6aec04c2ea85276a0075a2c1c23", - "0x0000000000000000000000000000000000000000000000000000000000002472": "0x4fab78dc66e82a775d0f1e00e5730eb22c197abfb86fa74fac0c17a6ec884a10", - "0x0000000000000000000000000000000000000000000000000000000000002471": "0x89fe746e22fbfc3e6e0fd28a16fdd025ec0a55e541c6cfb9ca4cf2e267ad36d2", - "0x0000000000000000000000000000000000000000000000000000000000000449": "0x000000000000000000000000000000000000000000000000000000006972389d", - "0x0000000000000000000000000000000000000000000000000000000000000467": "0x00000000000000000000000000000000000000000000000000000000697238bb", - "0x000000000000000000000000000000000000000000000000000000000000046d": "0x00000000000000000000000000000000000000000000000000000000697238c1", - "0x0000000000000000000000000000000000000000000000000000000000000459": "0x00000000000000000000000000000000000000000000000000000000697238ad", - "0x0000000000000000000000000000000000000000000000000000000000000480": "0x00000000000000000000000000000000000000000000000000000000697238d4", - "0x000000000000000000000000000000000000000000000000000000000000046a": "0x00000000000000000000000000000000000000000000000000000000697238be", - "0x000000000000000000000000000000000000000000000000000000000000246e": "0x37437855c2f7350a40a8d13cdd6997e2bc2fb5531b2ad11e3d878022bc6cc2ef", - "0x000000000000000000000000000000000000000000000000000000000000044b": "0x000000000000000000000000000000000000000000000000000000006972389f", - "0x000000000000000000000000000000000000000000000000000000000000247b": "0x62387a38188a4177d2d7954ff7dd6fa53bae25356db42cc561edb84eb2c87233", - "0x0000000000000000000000000000000000000000000000000000000000002484": "0x964204cbfafddd69550dc66ffd8369d85247dd43ec77f913f5d941bfb1aef5a6", - "0x0000000000000000000000000000000000000000000000000000000000000446": "0x000000000000000000000000000000000000000000000000000000006972389a", - "0x000000000000000000000000000000000000000000000000000000000000244d": "0x6b69c7e11c386d97a901d74d15173221785099d618a3bd905c4798591e2472a6", - "0x000000000000000000000000000000000000000000000000000000000000047e": "0x00000000000000000000000000000000000000000000000000000000697238d2", - "0x000000000000000000000000000000000000000000000000000000000000247e": "0x74eb6ef676ae8fc7c7fd21f7fc2308b496eb153a834e72c3f0890fb6bdf1027a", - "0x0000000000000000000000000000000000000000000000000000000000002475": "0x4e0767b9e97c8b49bdd1cedeff3bacb70b9a1b0d5c008e746d8f6ca2bfe0b610", - "0x0000000000000000000000000000000000000000000000000000000000002454": "0x6af7ccdca6c7c98a9279047724315c2a48be0f17f1c20c49296479f5d14aefbe", - "0x000000000000000000000000000000000000000000000000000000000000044f": "0x00000000000000000000000000000000000000000000000000000000697238a3", - "0x0000000000000000000000000000000000000000000000000000000000000485": "0x00000000000000000000000000000000000000000000000000000000697238d9", - "0x000000000000000000000000000000000000000000000000000000000000045d": "0x00000000000000000000000000000000000000000000000000000000697238b1", - "0x000000000000000000000000000000000000000000000000000000000000046e": "0x00000000000000000000000000000000000000000000000000000000697238c2", - "0x0000000000000000000000000000000000000000000000000000000000002449": "0x84d0222891c9e06c993a99d85ded6218fcdbc1c13c55a45e8d95851d119e4234", - "0x0000000000000000000000000000000000000000000000000000000000000458": "0x00000000000000000000000000000000000000000000000000000000697238ac", - "0x0000000000000000000000000000000000000000000000000000000000002457": "0x50eac8ce69fb0f0b0250d5e1690d50e928970394120694718f4bef7a5ea7ef71", - "0x000000000000000000000000000000000000000000000000000000000000248a": "0xd89df4ecf0e95207a664d1bec16a2e9277073f6f91a14ad8078de424e7bd8592", - "0x000000000000000000000000000000000000000000000000000000000000044c": "0x00000000000000000000000000000000000000000000000000000000697238a0", - "0x0000000000000000000000000000000000000000000000000000000000000473": "0x00000000000000000000000000000000000000000000000000000000697238c7", - "0x0000000000000000000000000000000000000000000000000000000000000455": "0x00000000000000000000000000000000000000000000000000000000697238a9", - "0x0000000000000000000000000000000000000000000000000000000000002467": "0xbc4f7e3a7d645c90b7a096e84809e183195081de63d5d502d6bf6cc32d4eeb98", - "0x0000000000000000000000000000000000000000000000000000000000000453": "0x00000000000000000000000000000000000000000000000000000000697238a7", - "0x000000000000000000000000000000000000000000000000000000000000245f": "0x361f87740b2f1b0ed2365dffa2c4f3f0eb12f5f66221cfd9aa3a568cd9abceb4", - "0x0000000000000000000000000000000000000000000000000000000000002461": "0xf6a83841edf8fcb1e66e37743a2f869d60fe6c79f9787f0c84f68a225d0b11d4", - "0x0000000000000000000000000000000000000000000000000000000000002444": "0x7c6c245445dbdff3e71cf089d2db408405f961c7e4d361e6570ca432cf6d55d7", - "0x0000000000000000000000000000000000000000000000000000000000002486": "0xa201b506d37d418fdcd45dfd467c5476cdd5f96c09a1399511d48b3d4658474f", - "0x0000000000000000000000000000000000000000000000000000000000000470": "0x00000000000000000000000000000000000000000000000000000000697238c4", - "0x000000000000000000000000000000000000000000000000000000000000248b": "0x2d890eaeeb3c19a7baeb9658df1db21f185a8fe4984771df4d4dd149ce6b64f9", - "0x000000000000000000000000000000000000000000000000000000000000045e": "0x00000000000000000000000000000000000000000000000000000000697238b2", - "0x000000000000000000000000000000000000000000000000000000000000247d": "0x975e0c76ac8bb18586d96588faf09997ef0a4bad33b7cf7d2a07615cbcb036d2", - "0x000000000000000000000000000000000000000000000000000000000000245c": "0xb24731b36d9fb45d3fd28f64bb879f2bdd27dcee352e35af2f59c2aecdfaea20", - "0x000000000000000000000000000000000000000000000000000000000000047f": "0x00000000000000000000000000000000000000000000000000000000697238d3", - "0x000000000000000000000000000000000000000000000000000000000000048a": "0x00000000000000000000000000000000000000000000000000000000697238de", - "0x0000000000000000000000000000000000000000000000000000000000002447": "0x5fcdf63ed9ee4714d8d3b3370b4a5bd51ba0cddb4ceaad028008cc68a5c3bfe0", - "0x0000000000000000000000000000000000000000000000000000000000000483": "0x00000000000000000000000000000000000000000000000000000000697238d7", - "0x000000000000000000000000000000000000000000000000000000000000044d": "0x00000000000000000000000000000000000000000000000000000000697238a1", - "0x000000000000000000000000000000000000000000000000000000000000245a": "0xccc53e889e3c202cf57575e55088445204e2ceebeab3987d768f831489a8e493", - "0x000000000000000000000000000000000000000000000000000000000000045f": "0x00000000000000000000000000000000000000000000000000000000697238b3", - "0x0000000000000000000000000000000000000000000000000000000000000469": "0x00000000000000000000000000000000000000000000000000000000697238bd", - "0x000000000000000000000000000000000000000000000000000000000000244a": "0x23527ac268bd603cea37ad3ec137101dd9723dfb020e552ed86221773c947137", - "0x000000000000000000000000000000000000000000000000000000000000048f": "0x00000000000000000000000000000000000000000000000000000000697238e3", - "0x0000000000000000000000000000000000000000000000000000000000002465": "0xd1c1d44101783386ccb22f699b186a5654be2f1c972688c03c8b0304a5442f42", - "0x000000000000000000000000000000000000000000000000000000000000247a": "0x9220ecb05dbc583364c680ac30fd504cd953b2cada6899b750b4430a5bcc6512", - "0x000000000000000000000000000000000000000000000000000000000000247c": "0x7d37f7705914d62e2de5f5c4ca5bbf599dbb885c225c6672466f05ee99c1fe12", - "0x0000000000000000000000000000000000000000000000000000000000000451": "0x00000000000000000000000000000000000000000000000000000000697238a5", - "0x0000000000000000000000000000000000000000000000000000000000000465": "0x00000000000000000000000000000000000000000000000000000000697238b9", - "0x000000000000000000000000000000000000000000000000000000000000244b": "0x8dc2ff3299d70c7408b8ba2bd6d72f18fba95038594bae40d704faeca438b76d", - "0x0000000000000000000000000000000000000000000000000000000000002480": "0x78123ad8ce4dc49e0b9e5c1b998efed203276d16301231b1defe29d1c4f31409", - "0x0000000000000000000000000000000000000000000000000000000000000487": "0x00000000000000000000000000000000000000000000000000000000697238db", - "0x000000000000000000000000000000000000000000000000000000000000245b": "0xf5fd7f142382a8b3036a73581409a1a81f4253976a2f45a262a4aef542b25682", - "0x0000000000000000000000000000000000000000000000000000000000000463": "0x00000000000000000000000000000000000000000000000000000000697238b7", - "0x000000000000000000000000000000000000000000000000000000000000248c": "0x796c897719d317d104b3fe0e3dd718a16ccaac62a03fe792f06ab1860b020bcd", - "0x0000000000000000000000000000000000000000000000000000000000000479": "0x00000000000000000000000000000000000000000000000000000000697238cd", - "0x0000000000000000000000000000000000000000000000000000000000000482": "0x00000000000000000000000000000000000000000000000000000000697238d6", - "0x0000000000000000000000000000000000000000000000000000000000002456": "0xf2329f0610d54dd62dad2ff6b2ce7e044c563f0330486248487b5649a8e57f32", - "0x0000000000000000000000000000000000000000000000000000000000002450": "0x629f40464f808b00779cce29a20b44678ad27fbab164b52b3ce65f91c6991892", - "0x0000000000000000000000000000000000000000000000000000000000002458": "0xe039f05481865865b1ed65b8afb07a1878e3e39841cd102fd7adc7b2d10f66a2", - "0x000000000000000000000000000000000000000000000000000000000000248d": "0x06a8c2d710b8466d9610c5390735fcd8cda2db8346ec894711ed34c2a44e3370", - "0x0000000000000000000000000000000000000000000000000000000000000476": "0x00000000000000000000000000000000000000000000000000000000697238ca", - "0x000000000000000000000000000000000000000000000000000000000000048e": "0x00000000000000000000000000000000000000000000000000000000697238e2", - "0x000000000000000000000000000000000000000000000000000000000000248e": "0xe80b58c8fb6c38cee7e89906f5bc67db0c3d795ce038e20fa772838e0dfda9d9", - "0x0000000000000000000000000000000000000000000000000000000000002452": "0x5ce6c063ba5a96a2bf7dc17a7e440256a030a76d31512d281f72f2e5fc12d212", - "0x000000000000000000000000000000000000000000000000000000000000245e": "0x8da6e81a5056bf532fc1b9359030ce3d92460ae7597a082499a857b25733d1c1", - "0x0000000000000000000000000000000000000000000000000000000000000481": "0x00000000000000000000000000000000000000000000000000000000697238d5", - "0x0000000000000000000000000000000000000000000000000000000000000474": "0x00000000000000000000000000000000000000000000000000000000697238c8", - "0x0000000000000000000000000000000000000000000000000000000000002466": "0x5d9f43d718821f409ab035232280df2095ee3993eb0cd732051129a3a411e357", - "0x0000000000000000000000000000000000000000000000000000000000002473": "0x1f0a9590c08c416f865a99aa629f215e81a309a9c9aba561417ad52e75cee459", - "0x0000000000000000000000000000000000000000000000000000000000000447": "0x000000000000000000000000000000000000000000000000000000006972389b", - "0x000000000000000000000000000000000000000000000000000000000000246b": "0xe52553027455ae41c0df271964e3ed9620cab07cf058f391c42ad253128d9408", - "0x000000000000000000000000000000000000000000000000000000000000047c": "0x00000000000000000000000000000000000000000000000000000000697238d0", - "0x000000000000000000000000000000000000000000000000000000000000047a": "0x00000000000000000000000000000000000000000000000000000000697238ce", - "0x000000000000000000000000000000000000000000000000000000000000246a": "0xa4a069f58ddcd2f73c87dbfef895ba67c96701708c32924f4a6d567abc54ec19", - "0x0000000000000000000000000000000000000000000000000000000000000460": "0x00000000000000000000000000000000000000000000000000000000697238b4", - "0x0000000000000000000000000000000000000000000000000000000000000454": "0x00000000000000000000000000000000000000000000000000000000697238a8", - "0x000000000000000000000000000000000000000000000000000000000000247f": "0x4cc2003f4ae9925d2a0f1f58f9fbc34d75ee9d1b7e6271be78e4245e8405efa7", - "0x0000000000000000000000000000000000000000000000000000000000002451": "0x5154642f458e86b9582eb0fd4aca5288cc0ea430a2e308314371da24755dd95f", - "0x0000000000000000000000000000000000000000000000000000000000002489": "0x604959dff65a1deba1c3991c69ad92d426b51611b8ae98dc8b982968a598c82d", - "0x0000000000000000000000000000000000000000000000000000000000000466": "0x00000000000000000000000000000000000000000000000000000000697238ba", - "0x000000000000000000000000000000000000000000000000000000000000045c": "0x00000000000000000000000000000000000000000000000000000000697238b0", - "0x0000000000000000000000000000000000000000000000000000000000000468": "0x00000000000000000000000000000000000000000000000000000000697238bc", - "0x0000000000000000000000000000000000000000000000000000000000000484": "0x00000000000000000000000000000000000000000000000000000000697238d8", - "0x0000000000000000000000000000000000000000000000000000000000000462": "0x00000000000000000000000000000000000000000000000000000000697238b6", - "0x000000000000000000000000000000000000000000000000000000000000245d": "0x2a3a6a49c7046f8e971535952dd1b34f0cc33f367abfd57436a9ace6f750eba1", - "0x0000000000000000000000000000000000000000000000000000000000002460": "0x06d272c823662455995135fa2bf92acd5ccc1f7b80373c4778d36b160e887d33", - "0x0000000000000000000000000000000000000000000000000000000000002445": "0xfdab1d1c2672259525cd5a4526712c6c4cff3d874cbac051aee655524edda829", - "0x000000000000000000000000000000000000000000000000000000000000244e": "0xf8fd49a0aaf9939561aa4e3c7689c80f15c4106fd61eb3168f8ef2018b49a3e2", - "0x0000000000000000000000000000000000000000000000000000000000002488": "0x7247670d4d2a5f80683ab9552c4d780b0dc746bda5d9a70206635391d24dd59e", - "0x000000000000000000000000000000000000000000000000000000000000044e": "0x00000000000000000000000000000000000000000000000000000000697238a2", - "0x000000000000000000000000000000000000000000000000000000000000244c": "0x89c81eba17ac01f4397bf7c932b0a1db58b2dcc4356f1c8e3bbf8a5b6e823104", - "0x000000000000000000000000000000000000000000000000000000000000044a": "0x000000000000000000000000000000000000000000000000000000006972389e", - "0x0000000000000000000000000000000000000000000000000000000000002464": "0xefdbcaca82d4ad681a074d716113b0ea592ae0520b0d2cfdd0e819c4361d713f", - "0x0000000000000000000000000000000000000000000000000000000000002485": "0x29c9375906d6d8f690b8bda099e31fc9428e27a290ba4dc471b9d271c8b7adbe", - "0x0000000000000000000000000000000000000000000000000000000000000457": "0x00000000000000000000000000000000000000000000000000000000697238ab", - "0x0000000000000000000000000000000000000000000000000000000000000475": "0x00000000000000000000000000000000000000000000000000000000697238c9", - "0x000000000000000000000000000000000000000000000000000000000000246f": "0xd9602aeb69c13b3752172f77bf144ca6d71bb21476bd90286d37c90a86239ae9", - "0x0000000000000000000000000000000000000000000000000000000000000450": "0x00000000000000000000000000000000000000000000000000000000697238a4", - "0x0000000000000000000000000000000000000000000000000000000000000471": "0x00000000000000000000000000000000000000000000000000000000697238c5", - "0x0000000000000000000000000000000000000000000000000000000000002468": "0x39e3e27cf9df76ec404ce6929a4d49369c8e6e06e53d59d46697dca84b9723ba", - "0x0000000000000000000000000000000000000000000000000000000000002477": "0x5ba2e6d3afa130be24ccb2ab8b259358c9f7cc6bb1ded34f30c2df041baa94a1", - "0x000000000000000000000000000000000000000000000000000000000000046b": "0x00000000000000000000000000000000000000000000000000000000697238bf", - "0x0000000000000000000000000000000000000000000000000000000000002483": "0x695736708364ed76c3d8113c6d71e6db0ef9739a00187c59bb1c85bebf82e3fb", - "0x000000000000000000000000000000000000000000000000000000000000246d": "0x43d28cffdc7c4e712a02531e9a82788db2db25ae097eeb508eea647fbd66b8ac", - "0x0000000000000000000000000000000000000000000000000000000000002463": "0x2a9e87d5c512b4eb9ab9b31b49e9ed2a138411c65f5b4332eb1f8218c338511b", - "0x0000000000000000000000000000000000000000000000000000000000000489": "0x00000000000000000000000000000000000000000000000000000000697238dd", - "0x000000000000000000000000000000000000000000000000000000000000048d": "0x00000000000000000000000000000000000000000000000000000000697238e1", - "0x0000000000000000000000000000000000000000000000000000000000002446": "0x1b0fb1d8777656036988eae201185a7e3bdd9e1d1ff66a83a28a1d3305e5d898", - "0x0000000000000000000000000000000000000000000000000000000000002470": "0x7c1c09193652ccb5b8f78cddf7a93adfde3f1460f8a225e8e35b93f9db7fe624", - "0x000000000000000000000000000000000000000000000000000000000000045b": "0x00000000000000000000000000000000000000000000000000000000697238af", - "0x0000000000000000000000000000000000000000000000000000000000002462": "0x5cd583c165373a7f2989274fb0e2a067dc174c983406a7a81ff287ea7aaff99a", - "0x0000000000000000000000000000000000000000000000000000000000000448": "0x000000000000000000000000000000000000000000000000000000006972389c", - "0x000000000000000000000000000000000000000000000000000000000000048b": "0x00000000000000000000000000000000000000000000000000000000697238df", - "0x0000000000000000000000000000000000000000000000000000000000000478": "0x00000000000000000000000000000000000000000000000000000000697238cc" - } - }, - "13": { - "address": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1", - "code": "0x608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80633659cfe6146100595780635c60da1b1461006e578063715018a6146100975780638da5cb5b1461009f578063f2fde38b146100af575b5f5ffd5b61006c6100673660046102d7565b6100c2565b005b6001546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b61006c610109565b5f546001600160a01b031661007b565b61006c6100bd3660046102d7565b61011c565b6100ca61019a565b6100d3816101f3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b61011161019a565b61011a5f610288565b565b61012461019a565b6001600160a01b03811661018e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61019781610288565b50565b5f546001600160a01b0316331461011a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610185565b6001600160a01b0381163b6102665760405162461bcd60e51b815260206004820152603360248201527f5570677261646561626c65426561636f6e3a20696d706c656d656e746174696f6044820152721b881a5cc81b9bdd08184818dbdb9d1c9858dd606a1b6064820152608401610185565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156102e7575f5ffd5b81356001600160a01b03811681146102fd575f5ffd5b939250505056fea2646970667358221220003d7f443094069cb023dc39fb36d6ba29922db6cd9b714ea95af972fc56405e64736f6c634300081c003300000000000000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x00000000000000000000000059b670e9fa9d0a427751af201d676719a970857b", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65" - } - }, - "14": { - "address": "0xBeaAFDA2E17fC95E69Dc06878039d274E0d2B21A", - "code": "0x608060405260043610610036575f3560e01c8063338c5371146100415780639bb66b2814610091578063e905182a146100be575f5ffd5b3661003d57005b5f5ffd5b34801561004c575f5ffd5b506100747f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f8168881565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561009c575f5ffd5b506100b06100ab3660046101ae565b6100ff565b604051610088929190610239565b3480156100c9575f5ffd5b506100f17f03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131481565b604051908152602001610088565b5f6060336001600160a01b037f0000000000000000000000009d4454b023096f34b160d6b654540c56a1f81688161461014a576040516282b42960e81b815260040160405180910390fd5b846001600160a01b03168484604051610164929190610277565b5f60405180830381855af49150503d805f811461019c576040519150601f19603f3d011682016040523d82523d5f602084013e6101a1565b606091505b5091509150935093915050565b5f5f5f604084860312156101c0575f5ffd5b83356001600160a01b03811681146101d6575f5ffd5b9250602084013567ffffffffffffffff8111156101f1575f5ffd5b8401601f81018613610201575f5ffd5b803567ffffffffffffffff811115610217575f5ffd5b866020828401011115610228575f5ffd5b939660209190910195509293505050565b8215158152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b818382375f910190815291905056fea26469706673582212208fe760f358faedf4a90fd4b23c39c8397def11c5b035ea1406af976ecc426bbf64736f6c634300081c00330000000000", - "storage": {} - }, - "12": { - "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", - "code": "0x735fbdb2315678afecb367f032d93f642f64180aa33014608060405260043610610034575f3560e01c8063e5bad8da14610038575b5f5ffd5b61004b610046366004610256565b61005f565b604051901515815260200160405180910390f35b5f80610079610073368590038501856102fc565b85610104565b90506001600160a01b03851663a401662b8261009860c087018761039b565b8760e001356040518563ffffffff1660e01b81526004016100bc94939291906103e8565b602060405180830381865afa1580156100d7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100fb919061042c565b95945050505050565b81515f90819060f81b61013c8560200151600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1760e01b90565b85604001516101b287606001515f65ff000000ff00600883811b91821664ff000000ff9185901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b92915050565b6080880151600881811b63ff00ff001662ff00ff9290911c9190911617601081811b91901c1760e01b60a08901516040516001600160f81b031990961660208701526001600160e01b0319948516602187015260258601939093526001600160c01b0319909116604585015291909116604d83015260518201526071810184905260910160408051808303601f190181529190528051602090910120949350505050565b5f5f5f60608486031215610268575f5ffd5b83356001600160a01b038116811461027e575f5ffd5b925060208401359150604084013567ffffffffffffffff8111156102a0575f5ffd5b840161010081870312156102b2575f5ffd5b809150509250925092565b803560ff811681146102cd575f5ffd5b919050565b803563ffffffff811681146102cd575f5ffd5b803567ffffffffffffffff811681146102cd575f5ffd5b5f60c082840312801561030d575f5ffd5b5060405160c0810167ffffffffffffffff8111828210171561033d57634e487b7160e01b5f52604160045260245ffd5b604052610349836102bd565b8152610357602084016102d2565b602082015260408381013590820152610372606084016102e5565b6060820152610383608084016102d2565b608082015260a0928301359281019290925250919050565b5f5f8335601e198436030181126103b0575f5ffd5b83018035915067ffffffffffffffff8211156103ca575f5ffd5b6020019150600581901b36038213156103e1575f5ffd5b9250929050565b84815260606020820181905281018390525f6001600160fb1b0384111561040d575f5ffd5b8360051b80866080850137604083019390935250016080019392505050565b5f6020828403121561043c575f5ffd5b8151801515811461044b575f5ffd5b939250505056fea2646970667358221220202aa32fed9b1043addbc14e73c73106e521b4a0cbd4090b88a279664688a3ca64736f6c634300081c0033000000000000000000000000", - "storage": {} - }, - "29": { - "address": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0x38de7073e27519f272741044a68ab5a51022aa002af20801e32867226a9bb4bd": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x9254291d7d424716ad6728e8cf28d7329070cafa88280734e18f0a5f711cc416": "0x000000000000000000000000998abeb3e57409262ae5b751f60747921b33613e", - "0x288c6faa56b91953378099dc2014a331affa988ca357fe83ca55e72915585282": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x4bad58e84dc127f47e7265bd5e504be070126f63f93af282fe2a4f1acbb07707": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x165183f4d7a8ecead93a30c1491a78d70b212627d72d451cc2b61e9844bb6182": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000c5a5c42992decbae36851359345fe25997f5c42d", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x54ab5bc83c0127df10d352dbba9557880cef93f87419916bd513c73a26e9de39": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788" - } - }, - "1": { - "address": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6", - "code": "0x732279b7a0a67db372996a5fab50d91eaa73d2ebe63014608060405260043610610034575f3560e01c8063a3499c7314610038575b5f5ffd5b818015610043575f5ffd5b50610057610052366004610230565b610059565b005b61006b836001600160a01b03166101b3565b610088576040516303777f6960e51b815260040160405180910390fd5b81836001600160a01b03163f146100b2576040516323e13ec960e21b815260040160405180910390fd5b6100da837f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b5f5f846001600160a01b0316836040516024016100f79190610309565b60408051601f198184030181529181526020820180516001600160e01b031663439fab9160e01b1790525161012c919061033e565b5f60405180830381855af49150503d805f8114610164576040519150601f19603f3d011682016040523d82523d5f602084013e610169565b606091505b509150915061017882826101fd565b506040516001600160a01b038616907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a25050505050565b5f6001600160a01b0382163f158015906101f757507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4706001600160a01b0383163f14155b92915050565b6060821561020c5750806101f7565b8151156100345781518083602001fd5b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610242575f5ffd5b83356001600160a01b0381168114610258575f5ffd5b925060208401359150604084013567ffffffffffffffff81111561027a575f5ffd5b8401601f8101861361028a575f5ffd5b803567ffffffffffffffff8111156102a4576102a461021c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156102d3576102d361021c565b6040528181528282016020018810156102ea575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f82518060208501845e5f92019182525091905056fea26469706673582212204f9eff25a489952d6ace57dae13f4311e26f51d13db35754950e1446aa6c4c3264736f6c634300081c003300", - "storage": {} - }, "2": { - "address": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933", - "code": "0x608060405234801561000f575f5ffd5b50600436106100e5575f3560e01c80639100674511610088578063ad8aca7711610063578063ad8aca77146101df578063df595cb8146101f2578063eb5a4e8714610205578063fddbdefd14610218575f5ffd5b80639100674514610196578063950d806e146101b9578063ad5f2210146101cc575f5ffd5b806354fd4d50116100c357806354fd4d5014610124578063628806ef146101425780636bddfa1f14610155578063882a3b3814610175575f5ffd5b806306641201146100e9578063268959e5146100fe5780634f906cf914610111575b5f5ffd5b6100fc6100f7366004610dbd565b61022b565b005b6100fc61010c366004610e0e565b61034c565b6100fc61011f366004610e0e565b610427565b61012c6104ca565b6040516101399190610e3f565b60405180910390f35b6100fc610150366004610e74565b6104fa565b610168610163366004610e74565b610588565b6040516101399190610ed0565b610188610183366004610e0e565b6105b1565b604051610139929190610ee2565b6101a96101a4366004610e0e565b610712565b6040519015158152602001610139565b6100fc6101c7366004610dbd565b610782565b6101686101da366004610e74565b610893565b6101a96101ed366004610e0e565b610939565b6101a9610200366004610dbd565b61095a565b6100fc610213366004610e0e565b6109af565b610168610226366004610f44565b610a7d565b836102368133610712565b61025357604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600160205260408120906102758585610abb565b6001600160a01b0387165f908152600484016020526040902090915061029b9082610ae8565b6102b85760405163262118cd60e01b815260040160405180910390fd5b6001600160a01b0386165f90815260048301602052604090206102db9082610aff565b505f81815260058301602052604090206102f59087610b0a565b50856001600160a01b0316876001600160a01b03167f18242326b6b862126970679759169f01f646bd55ec5bfcab85ba9f337a74e0c6878760405161033b929190610f84565b60405180910390a350505050505050565b816103578133610712565b61037457604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526001602081905260409091206002019061039b82610b1e565b116103b9576040516310ce892b60e31b815260040160405180910390fd5b6103c38184610b0a565b6103e057604051630716d81b60e51b815260040160405180910390fd5b6040516001600160a01b0384811682528516907fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce906020015b60405180910390a250505050565b816104328133610712565b61044f57604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526001602052604090206104708184610b0a565b61048d5760405163bed8295f60e01b815260040160405180910390fd5b6040516001600160a01b0384811682528516907fd706ed7ae044d795b49e54c9f519f663053951011985f663a862cd9ee72a9ac790602001610419565b60606104f57f76312e302e300000000000000000000000000000000000000000000000000006610b27565b905090565b6001600160a01b0381165f90815260016020526040902061051b8133610b0a565b6105385760405163bed8295f60e01b815260040160405180910390fd5b6105456002820133610b64565b506040513381526001600160a01b038316907fbf265e8326285a2747e33e54d5945f7111f2b5edb826eb8c08d4677779b3ff979060200160405180910390a25050565b6001600160a01b0381165f9081526001602052604090206060906105ab90610b78565b92915050565b6001600160a01b038083165f9081526001602090815260408083209385168352600490930190529081206060918291906105ea82610b1e565b90505f8167ffffffffffffffff81111561060657610606610fa7565b60405190808252806020026020018201604052801561062f578160200160208202803683370190505b5090505f8267ffffffffffffffff81111561064c5761064c610fa7565b604051908082528060200260200182016040528015610675578160200160208202803683370190505b5090505f5b83811015610704576106a861068f8683610b84565b606081901c9160a09190911b6001600160e01b03191690565b8483815181106106ba576106ba610fbb565b602002602001018484815181106106d3576106d3610fbb565b6001600160e01b0319909316602093840291909101909201919091526001600160a01b03909116905260010161067a565b509097909650945050505050565b6001600160a01b0382165f90815260016020526040812061073590600201610b1e565b5f0361075757816001600160a01b0316836001600160a01b03161490506105ab565b6001600160a01b0383165f90815260016020526040902061077b9060020183610b8f565b9392505050565b8361078d8133610712565b6107aa57604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0385165f908152600160205260408120906107cc8585610abb565b6001600160a01b0387165f90815260048401602052604090209091506107f29082610ae8565b156108105760405163ad8efeb760e01b815260040160405180910390fd5b6001600160a01b0386165f90815260048301602052604090206108339082610bb0565b505f818152600583016020526040902061084d9087610b64565b50856001600160a01b0316876001600160a01b03167f037f03a2ad6b967df4a01779b6d2b4c85950df83925d9e31362b519422fc0169878760405161033b929190610f84565b6001600160a01b0381165f9081526001602052604090206060906108b990600201610b1e565b5f03610911576040805160018082528183019092525f916020808301908036833701905050905082815f815181106108f3576108f3610fbb565b6001600160a01b039092166020928302919091019091015292915050565b6001600160a01b0382165f9081526001602052604090206105ab90600201610b78565b919050565b6001600160a01b0382165f90815260016020526040812061077b9083610b8f565b5f6109658585610712565b806109a657506109a66109788484610abb565b6001600160a01b038088165f908152600160209081526040808320938a168352600490930190522090610ae8565b95945050505050565b816109ba8133610712565b6109d757604051637bfa4b9f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526001602052604090206109fb6002820184610b8f565b15610a195760405163130160e560e31b815260040160405180910390fd5b610a238184610b64565b610a40576040516319abede360e11b815260040160405180910390fd5b6040516001600160a01b0384811682528516907fb14b9a3d448c5b04f0e5b087b6f5193390db7955482a6ffb841e7b3ba61a460c90602001610419565b60605f610a8a8484610abb565b6001600160a01b0386165f90815260016020908152604080832084845260050190915290209091506109a690610b78565b60609190911b6bffffffffffffffffffffffff191660a09190911c6bffffffff0000000000000000161790565b5f818152600183016020526040812054151561077b565b5f61077b8383610bbb565b5f61077b836001600160a01b038416610bbb565b5f6105ab825490565b60605f610b3383610c9e565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f61077b836001600160a01b038416610cc5565b60605f61077b83610d11565b5f61077b8383610d6a565b6001600160a01b0381165f908152600183016020526040812054151561077b565b5f61077b8383610cc5565b5f8181526001830160205260408120548015610c95575f610bdd600183610fcf565b85549091505f90610bf090600190610fcf565b9050818114610c4f575f865f018281548110610c0e57610c0e610fbb565b905f5260205f200154905080875f018481548110610c2e57610c2e610fbb565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610c6057610c60610fee565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105ab565b5f9150506105ab565b5f60ff8216601f8111156105ab57604051632cd44ac360e21b815260040160405180910390fd5b5f818152600183016020526040812054610d0a57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105ab565b505f6105ab565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610d5e57602002820191905f5260205f20905b815481526020019060010190808311610d4a575b50505050509050919050565b5f825f018281548110610d7f57610d7f610fbb565b905f5260205f200154905092915050565b80356001600160a01b0381168114610934575f5ffd5b80356001600160e01b031981168114610934575f5ffd5b5f5f5f5f60808587031215610dd0575f5ffd5b610dd985610d90565b9350610de760208601610d90565b9250610df560408601610d90565b9150610e0360608601610da6565b905092959194509250565b5f5f60408385031215610e1f575f5ffd5b610e2883610d90565b9150610e3660208401610d90565b90509250929050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610e84575f5ffd5b61077b82610d90565b5f8151808452602084019350602083015f5b82811015610ec65781516001600160a01b0316865260209586019590910190600101610e9f565b5093949350505050565b602081525f61077b6020830184610e8d565b604081525f610ef46040830185610e8d565b82810360208401528084518083526020830191506020860192505f5b81811015610f385783516001600160e01b031916835260209384019390920191600101610f10565b50909695505050505050565b5f5f5f60608486031215610f56575f5ffd5b610f5f84610d90565b9250610f6d60208501610d90565b9150610f7b60408501610da6565b90509250925092565b6001600160a01b039290921682526001600160e01b031916602082015260400190565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b818103818111156105ab57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea26469706673582212205138500ca3c7de3b4f716056e14d380d984b3b127ee87718876d2d91dcf14c6d64736f6c634300081c003300000000", + "address": "0x00000000219ab540356cBB839Cbe05303d7705Fa", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033000000000000000000", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "22": { - "address": "0x95401dc811bb5740090279Ba06cfA8fcF6113778", - "code": "0x608060405234801561000f575f5ffd5b50600436106100cb575f3560e01c806342966c681161008857806395d89b411161006357806395d89b41146101a7578063a457c2d7146101af578063a9059cbb146101c2578063dd62ed3e146101d5575f5ffd5b806342966c681461015757806370a082311461016c57806379cc679014610194575f5ffd5b806306fdde03146100cf578063095ea7b3146100ed57806318160ddd1461011057806323b872dd14610122578063313ce567146101355780633950935114610144575b5f5ffd5b6100d76101e8565b6040516100e49190610826565b60405180910390f35b6101006100fb366004610876565b610278565b60405190151581526020016100e4565b6002545b6040519081526020016100e4565b61010061013036600461089e565b610291565b604051601281526020016100e4565b610100610152366004610876565b6102b4565b61016a6101653660046108d8565b6102d5565b005b61011461017a3660046108ef565b6001600160a01b03165f9081526020819052604090205490565b61016a6101a2366004610876565b6102e2565b6100d76102fb565b6101006101bd366004610876565b61030a565b6101006101d0366004610876565b610389565b6101146101e336600461090f565b610396565b6060600380546101f790610940565b80601f016020809104026020016040519081016040528092919081815260200182805461022390610940565b801561026e5780601f106102455761010080835404028352916020019161026e565b820191905f5260205f20905b81548152906001019060200180831161025157829003601f168201915b5050505050905090565b5f336102858185856103c0565b60019150505b92915050565b5f3361029e8582856104e4565b6102a985858561055c565b506001949350505050565b5f336102858185856102c68383610396565b6102d09190610978565b6103c0565b6102df33826106fe565b50565b6102ed8233836104e4565b6102f782826106fe565b5050565b6060600480546101f790610940565b5f33816103178286610396565b90508381101561037c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a982868684036103c0565b5f3361028581858561055c565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104225760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610373565b6001600160a01b0382166104835760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610373565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b5f6104ef8484610396565b90505f19811461055657818110156105495760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610373565b61055684848484036103c0565b50505050565b6001600160a01b0383166105c05760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610373565b6001600160a01b0382166106225760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610373565b6001600160a01b0383165f90815260208190526040902054818110156106995760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610373565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610556565b6001600160a01b03821661075e5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610373565b6001600160a01b0382165f90815260208190526040902054818110156107d15760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610373565b6001600160a01b0383165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91016104d7565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610871575f5ffd5b919050565b5f5f60408385031215610887575f5ffd5b6108908361085b565b946020939093013593505050565b5f5f5f606084860312156108b0575f5ffd5b6108b98461085b565b92506108c76020850161085b565b929592945050506040919091013590565b5f602082840312156108e8575f5ffd5b5035919050565b5f602082840312156108ff575f5ffd5b6109088261085b565b9392505050565b5f5f60408385031215610920575f5ffd5b6109298361085b565b91506109376020840161085b565b90509250929050565b600181811c9082168061095457607f821691505b60208210810361097257634e487b7160e01b5f52602260045260245ffd5b50919050565b8082018082111561028b57634e487b7160e01b5f52601160045260245ffdfea26469706673582212200294a24180b18f81e47bb4c278ebbaa0cad18043e20afac6f0159b7940a7867a64736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000d3c21bcecceda1000000", - "0xd19bcde47e0ffe1c643525c3cff070e266ec404a07f499b41fcbc480ff16fff7": "0x0000000000000000000000000000000000000000000069e10de76676d0800000", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x54657374546f6b656e0000000000000000000000000000000000000000000012", - "0x14e04a66bf74771820a7400ff6cf065175b3d7eb25805a5bd1633b161af5d101": "0x0000000000000000000000000000000000000000000069e10de76676d0800000", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5445535400000000000000000000000000000000000000000000000000000008" - } - }, - "7": { - "address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", - "code": "0x73a513e6e4b8f2a923d98304ec87f64353c4d5c853301460806040526004361061009b575f3560e01c806338412ce51161006e57806338412ce514610150578063480ff0651461016f5780636f378c061461018e578063957cae98146101ad578063c7f62387146101c0575f5ffd5b806319a79b481461009f5780631b8d43b0146100c057806320606b70146100f457806330adf81f14610129575b5f5ffd5b8180156100aa575f5ffd5b506100be6100b9366004610a4d565b6101df565b005b8180156100cb575f5ffd5b506100df6100da366004610acf565b610346565b60405190151581526020015b60405180910390f35b61011b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6040519081526020016100eb565b61011b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b81801561015b575f5ffd5b506100df61016a366004610b10565b61036b565b81801561017a575f5ffd5b506100be610189366004610b10565b610384565b818015610199575f5ffd5b506100df6101a8366004610b10565b6103cf565b61011b6101bb366004610b43565b6103dc565b8180156101cb575f5ffd5b506100be6101da366004610b10565b6103ec565b834211156102005760405163068568f360e21b815260040160405180910390fd5b5f61020a8961042d565b6001600160a01b0389165f90815260028c016020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928c928c928c9290919061025983610b6e565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016102d292919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090505f6102f7828686866104dc565b9050886001600160a01b0316816001600160a01b03161461032b57604051638baa579f60e01b815260040160405180910390fd5b6103398b8a8a8a6001610502565b5050505050505050505050565b5f610353858533856105f0565b506103608585858561067c565b506001949350505050565b5f61037a843385856001610502565b5060019392505050565b5f6001600160a01b0383166103bd57604051639cfea58360e01b81526001600160a01b0390911660048201526024015b60405180910390fd5b506103ca835f84846106f8565b505050565b5f61037a8433858561067c565b5f6103e68261042d565b92915050565b5f6001600160a01b038316610420576040516313053d9360e21b81526001600160a01b0390911660048201526024016103b4565b506103ca83835f846106f8565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8260405161045d9190610b86565b60408051918290038220828201825260018352603160f81b6020938401528151928301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c001604051602081830303815290604052805190602001209050919050565b5f5f5f6104eb87878787610829565b915091506104f8816108e6565b5095945050505050565b5f6001600160a01b038516610536576040516322f051b160e21b81526001600160a01b0390911660048201526024016103b4565b505f6001600160a01b03841661056b5760405163270af7ed60e11b81526001600160a01b0390911660048201526024016103b4565b506001600160a01b038085165f908152600187016020908152604080832093871683529290522082905580156105e957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516105e091815260200190565b60405180910390a35b5050505050565b6001600160a01b038084165f90815260018601602090815260408083209386168352929052908120545f198114610670578381848082101561065e57604051630c95cf2760e11b81526001600160a01b039093166004840152602483019190915260448201526064016103b4565b5050506106708686868685035f610502565b50600195945050505050565b5f6001600160a01b0384166106b0576040516313053d9360e21b81526001600160a01b0390911660048201526024016103b4565b505f6001600160a01b0383166106e557604051639cfea58360e01b81526001600160a01b0390911660048201526024016103b4565b506106f2848484846106f8565b50505050565b6001600160a01b0383166107245780846003015f8282546107199190610c22565b9091555061079a9050565b6001600160a01b0383165f90815260208590526040902054838183808210156107795760405163db42144d60e01b81526001600160a01b039093166004840152602483019190915260448201526064016103b4565b5050506001600160a01b0384165f9081526020869052604090209082900390555b6001600160a01b0382166107b85760038401805482900390556107d6565b6001600160a01b0382165f9081526020859052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161081b91815260200190565b60405180910390a350505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561085e57505f905060036108dd565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156108af573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b0381166108d7575f600192509250506108dd565b91505f90505b94509492505050565b5f8160048111156108f9576108f9610c35565b036109015750565b600181600481111561091557610915610c35565b036109625760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016103b4565b600281600481111561097657610976610c35565b036109c35760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016103b4565b60038160048111156109d7576109d7610c35565b03610a2f5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016103b4565b50565b80356001600160a01b0381168114610a48575f5ffd5b919050565b5f5f5f5f5f5f5f5f5f6101208a8c031215610a66575f5ffd5b8935985060208a01359750610a7d60408b01610a32565b9650610a8b60608b01610a32565b955060808a0135945060a08a0135935060c08a013560ff81168114610aae575f5ffd5b989b979a50959894979396929550929360e081013593506101000135919050565b5f5f5f5f60808587031215610ae2575f5ffd5b84359350610af260208601610a32565b9250610b0060408601610a32565b9396929550929360600135925050565b5f5f5f60608486031215610b22575f5ffd5b83359250610b3260208501610a32565b929592945050506040919091013590565b5f60208284031215610b53575f5ffd5b5035919050565b634e487b7160e01b5f52601160045260245ffd5b5f60018201610b7f57610b7f610b5a565b5060010190565b5f5f83545f8160011c90506001821680610ba157607f821691505b602082108103610bbf57634e487b7160e01b5f52602260045260245ffd5b808015610bd35760018114610be857610c16565b60ff1984168752821515830287019450610c16565b5f888152602090205f5b84811015610c0e57815489820152600190910190602001610bf2565b505082870194505b50929695505050505050565b808201808211156103e6576103e6610b5a565b634e487b7160e01b5f52602160045260245ffdfea26469706673582212207c195dc6c0dcf274cd547cf28d123e774d60cc2ca6ccfba9a4b62ae46152a83164736f6c634300081c003300", - "storage": {} - }, - "15": { - "address": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", - "code": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461010957806399a88ec41461011c578063f2fde38b1461013b578063f3b7dead1461015a575f5ffd5b8063204e1c7a1461007d578063715018a6146100b85780637eff275e146100ce5780638da5cb5b146100ed575b5f5ffd5b348015610088575f5ffd5b5061009c610097366004610479565b610179565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c3575f5ffd5b506100cc610204565b005b3480156100d9575f5ffd5b506100cc6100e836600461049b565b610217565b3480156100f8575f5ffd5b505f546001600160a01b031661009c565b6100cc6101173660046104e6565b61027a565b348015610127575f5ffd5b506100cc61013636600461049b565b6102e5565b348015610146575f5ffd5b506100cc610155366004610479565b61031b565b348015610165575f5ffd5b5061009c610174366004610479565b610399565b5f5f5f836001600160a01b031660405161019d90635c60da1b60e01b815260040190565b5f60405180830381855afa9150503d805f81146101d5576040519150601f19603f3d011682016040523d82523d5f602084013e6101da565b606091505b5091509150816101e8575f5ffd5b808060200190518101906101fc91906105bd565b949350505050565b61020c6103bd565b6102155f610416565b565b61021f6103bd565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b5f604051808303815f87803b158015610260575f5ffd5b505af1158015610272573d5f5f3e3d5ffd5b505050505050565b6102826103bd565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102b290869086906004016105d8565b5f604051808303818588803b1580156102c9575f5ffd5b505af11580156102db573d5f5f3e3d5ffd5b5050505050505050565b6102ed6103bd565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe690602401610249565b6103236103bd565b6001600160a01b03811661038d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61039681610416565b50565b5f5f5f836001600160a01b031660405161019d906303e1469160e61b815260040190565b5f546001600160a01b031633146102155760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610384565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610396575f5ffd5b5f60208284031215610489575f5ffd5b813561049481610465565b9392505050565b5f5f604083850312156104ac575f5ffd5b82356104b781610465565b915060208301356104c781610465565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f606084860312156104f8575f5ffd5b833561050381610465565b9250602084013561051381610465565b9150604084013567ffffffffffffffff81111561052e575f5ffd5b8401601f8101861361053e575f5ffd5b803567ffffffffffffffff811115610558576105586104d2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610587576105876104d2565b60405281815282820160200188101561059e575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f602082840312156105cd575f5ffd5b815161049481610465565b60018060a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f830116840101915050939250505056fea2646970667358221220d1857c1d79adf09a4456300c200565d4db0d5bcc151c34d3d6a7ed403fb9defd64736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65" - } - }, - "16": { - "address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", - "code": "0x73e7f1725e7734ce288f8367e1bb143e90bb3f0512301460806040526004361061009b575f3560e01c80632a6c32291161006e5780632a6c322914610191578063805ce31d146101c5578063928bc49d146101db57806399056fcc146101ee578063fe61cc491461020d575f5ffd5b80630705f4651461009f57806309824a80146100c85780630b617646146100e957806326aa101f1461014a575b5f5ffd5b6100b26100ad366004611fdf565b61026c565b6040516100bf919061200a565b60405180910390f35b8180156100d3575f5ffd5b506100e76100e236600461203a565b610282565b005b7f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f6547f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f754604080519283526001600160801b039091166020830152016100bf565b61018161015836600461203a565b6001600160a01b03165f9081525f5160206125e85f395f51905f52602052604090205460ff1690565b60405190151581526020016100bf565b6101a461019f366004611fdf565b61033b565b6040805167ffffffffffffffff9384168152929091166020830152016100bf565b6101cd61036a565b6040519081526020016100bf565b6101cd6101e936600461207c565b610380565b8180156101f9575f5ffd5b506100e76102083660046120bc565b6103e0565b61025461021b366004611fdf565b5f9081527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016100bf565b5f5f61027783610494565b5460ff169392505050565b5f5160206125e85f395f51905f52610299826104ef565b60408051608081019091526001820154600160a01b900463ffffffff1681525f90602081016102c6610586565b815260028401546020909101906102e79086906001600160801b03166105e7565b81525f6020918201526040516001600160a01b03861681529192507ff78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7e910160405180910390a161033681610632565b505050565b5f5f5f61034784610494565b5467ffffffffffffffff6101008204811696600160481b90920416945092505050565b5f61037b610376610586565b610836565b905090565b6001600160a01b0383165f9081525f5160206125e85f395f51905f52602081905260408220805460ff166103c75760405163259ba1ad60e01b815260040160405180910390fd5b6103d461037686866108c7565b925050505b9392505050565b5f5160206125e85f395f51905f526001600160801b0382165f036104175760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0387165f908152602082905260409020805460ff166104505760405163259ba1ad60e01b815260040160405180910390fd5b60018101546104745761046f61046a8989898989896109ae565b610632565b61048a565b61048a61046a82600101548a8a8a8a8a8a610b97565b5050505050505050565b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ac6020526040902060018101546001600160a01b03166104ea57604051636ddd9da960e01b815260040160405180910390fd5b919050565b610501816001600160a01b0316610cf9565b61051e5760405163c1ab6dc160e01b815260040160405180910390fd5b6001600160a01b0381165f9081525f5160206125e85f395f51905f5260208190526040909120805460ff168015610559575061055981610d3f565b1561057757604051633ea7ffd960e11b815260040160405180910390fd5b805460ff191660011790555050565b604080518082019091527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c230546001600160801b031681527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23154602082015290565b60605f6105f346610d53565b5f6105fd86610dbc565b61060686610ded565b60405160200161061a959493929190612161565b60405160208183030381529060405290505b92915050565b805160408051637061726160e01b60208083019190915260e09390931b6001600160e01b031916602482015281516008818303018152602890910190915280519101205f61067f82610494565b905061068a81610e8c565b5f6106988460200151610836565b90505f84606001516001600160801b0316826106b491906121c4565b9050803410156106d757604051631c0b171360e31b815260040160405180910390fd5b60608501516001600160801b0316156107225761072285606001516001600160801b031661070f5f5160206125e85f395f51905f5290565b600101546001600160a01b031690610f08565b825461074090600160481b900467ffffffffffffffff1660016121d7565b835467ffffffffffffffff91909116600160481b0270ffffffffffffffff000000000000000000199091161783555f61077982346121f7565b9050610783610f31565b811115610794576107943382610f08565b83546040805160208101889052600160481b90920460c01b6001600160c01b031916908201525f9060480160405160208183030381529060405280519060200120905080867f7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f875f0160099054906101000a900467ffffffffffffffff168a6040015160405161082592919061220a565b60405180910390a350505050505050565b80517f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f7545f917f59ef95eb9983b1a4650e1bc666384b8507689fc8aca3edd429d7e07c0ca9d2f691839161089c9161089791906001600160801b03166121c4565b610f3e565b90506108b0825f0154836002015483610f88565b84602001516108bf91906121c4565b949350505050565b604080518082019091525f80825260208201527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22f545f5160206125e85f395f51905f5290600160a01b900463ffffffff9081169085160361093e576002810154600160801b90046001600160801b031682526109a1565b60058101546001600160801b0361010090910481169084161115610975576040516332ee86af60e11b815260040160405180910390fd5b6002810154610995908490600160801b90046001600160801b0316612250565b6001600160801b031682525b505f602082015292915050565b6109b6611f9a565b5f5160206125e85f395f51905f526001600160a01b038816156109f85760018101546109ed906001600160a01b031689898661100d565b5f6060830152610a08565b6001600160801b03831660608301525b6001810154600160a01b900463ffffffff168252610a2686856108c7565b6020830152600181015463ffffffff808816600160a01b9092041603610a9f57610a4f85611089565b15610a8657610a7c88610a61876110b2565b6002840154600160801b90046001600160801b0316866110c9565b6040830152610b38565b604051634851657960e11b815260040160405180910390fd5b836001600160801b03165f03610ac8576040516332ee86af60e11b815260040160405180910390fd5b610ad185611089565b15610b0057610a7c8887610ae4886110b2565b6002850154600160801b90046001600160801b03168888611127565b610b09856111ba565b15610a8657610a7c8887610b1c886111c2565b6002850154600160801b90046001600160801b031688886111d9565b8563ffffffff16876001600160a01b0316896001600160a01b03167f24c5d2de620c6e25186ae16f6919eba93b6e2c1a33857cc419d9f3a00d6967e98887604051610b8492919061227d565b60405180910390a4509695505050505050565b610b9f611f9a565b5f5f5160206125e85f395f51905f52604051632770a7eb60e21b81526001600160a01b0389811660048301526001600160801b038616602483015291925090891690639dc29fac906044015f604051808303815f87803b158015610c01575f5ffd5b505af1158015610c13573d5f5f3e3d5ffd5b505050506001810154600160a01b900463ffffffff168252610c3586856108c7565b60208301525f6060830152600181015463ffffffff808816600160a01b90920416148015610c675750610c6785611089565b15610a8657610c9489610c79876110b2565b6002840154600160801b90046001600160801b031686611251565b60408301528563ffffffff16876001600160a01b0316896001600160a01b03167f24c5d2de620c6e25186ae16f6919eba93b6e2c1a33857cc419d9f3a00d6967e98887604051610ce592919061227d565b60405180910390a450979650505050505050565b5f6001600160a01b0382163f1580159061062c5750506001600160a01b03163f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470141590565b5f610d4c82600101541590565b1592915050565b5f65ff000000ff00600883811b91821664ff000000ff9185901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b92915050565b604051606082811b6001600160601b0319166020830152906034016040516020818303038152906040529050919050565b6eff000000ff000000ff000000ff0000600882811c9182166fff000000ff000000ff000000ff0000009390911b92831617601090811c6cff000000ff000000ff000000ff929092166dff000000ff000000ff000000ff00939093169290921790911b17602081811c6bffffffff00000000ffffffff166fffffffff00000000ffffffff000000009290911b9190911617604081811c91901b1760801b90565b7e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab80545f9060ff166001811115610ec457610ec4611ff6565b141580610ee657505f825460ff166001811115610ee357610ee3611ff6565b14155b15610f0457604051633ac4266d60e11b815260040160405180910390fd5b5050565b5f5f5f5f5f85875af190508061033657604051633d2cec6f60e21b815260040160405180910390fd5b5f61037b3a615208612323565b5f610f52670de0b6b3a76400005f1961234e565b821115610f7a57604051631cd951a760e01b8152600481018390526024015b60405180910390fd5b50670de0b6b3a76400000290565b5f5f5160206125e85f395f51905f5281610fa9670de0b6b3a7640000610f3e565b60058301549091505f90610fd390610fc39060ff16610f3e565b610fcd600a610f3e565b906112dd565b90505f610ff683610fea84610ff08c838d8d6113ed565b906113ed565b906113fb565b905061100181611412565b98975050505050505050565b61101f836001600160a01b0316610cf9565b61103c5760405163c1ab6dc160e01b815260040160405180910390fd5b806001600160801b03165f036110655760405163162908e360e11b815260040160405180910390fd5b6110836001600160a01b03841683866001600160801b038516611425565b50505050565b5f60015b61109a602084018461236d565b60028111156110ab576110ab611ff6565b1492915050565b5f6110c06020830183612386565b61062c916123d0565b60605f6110d546610d53565b600160f81b6110e388610dbc565b5f886110ee88610ded565b6110f78a610ded565b60405160200161110e9897969594939291906123ed565b6040516020818303038152906040529050949350505050565b60605f61113346610d53565b600160f81b6111418a610dbc565b600160f81b60088b811b63ff00ff001662ff00ff918d901c9190911617601081811b91901c1760e01b8a6111748a610ded565b61117d8a610ded565b6111868d610ded565b60405160200161119f9a9998979695949392919061245b565b60405160208183030381529060405290509695505050505050565b5f600261108d565b5f6111d06020830183612386565b61062c916124e3565b60605f6111e546610d53565b600160f81b6111f38a610dbc565b600160f91b60088b811b63ff00ff001662ff00ff918d901c9190911617601081811b91901c1760e01b8a6112268a610ded565b61122f8a610ded565b6112388d610ded565b60405160200161119f9a9998979695949392919061252b565b60605f61125d46610d53565b600160f91b875f8861126e88610ded565b6112778a610ded565b6040516001600160f81b031998891660208201526001600160c01b031990971660218801529487166029870152602a8601939093529416604a840152604b8301939093526001600160801b0319928316606b83015291909116607b820152608b0161110e565b5f82828183036113065780156112f3575f6112fd565b670de0b6b3a76400005b9250505061062c565b670de0b6b3a7640000820361132757670de0b6b3a76400009250505061062c565b805f0361134057670de0b6b3a76400009250505061062c565b670de0b6b3a7640000810361135957849250505061062c565b670de0b6b3a764000082111561138a5761138361137e6113788761147e565b866113ed565b6115a6565b92506113e5565b5f6113aa6113a7846ec097ce7bc90715b34b9f100000000061234e565b90565b90505f6113c261137e6113bc8461147e565b886113ed565b90506113e06113a7826ec097ce7bc90715b34b9f100000000061234e565b945050505b505092915050565b5f6103d96113a784846115fa565b5f6103d96113a784670de0b6b3a7640000856116ac565b5f61062c670de0b6b3a76400008361234e565b6040516001600160a01b038085166024830152831660448201526064810182905261108390859060840160408051601f198184030181529190526020810180516001600160e01b03166323b872dd60e01b17905261177b565b5f81670de0b6b3a76400008110156114ac5760405163036d32ef60e41b815260048101849052602401610f71565b5f61152e670de0b6b3a7640000830460016001600160801b03821160071b91821c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211871b91821c969096119490961792909217171791909117919091171790565b9050670de0b6b3a7640000810282821c670de0b6b3a763ffff1981016115575750949350505050565b671bc16d674ec800006706f05b59d3b200005b801561159a57670de0b6b3a7640000838002049250818310611592579283019260019290921c915b60011c61156a565b50919695505050505050565b5f81680a688906bd8affffff8111156115d55760405163b3b6ba1f60e01b815260048101849052602401610f71565b5f6115ec670de0b6b3a7640000604084901b61234e565b90506108bf6113a78261183a565b5f80805f19848609848602925082811083820303915050805f0361162b5750670de0b6b3a76400009004905061062c565b670de0b6b3a7640000811061165d57604051635173648d60e01b81526004810186905260248101859052604401610f71565b5f670de0b6b3a764000085870962040000818503049310909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690291505092915050565b5f80805f19858709858702925082811083820303915050805f036116e3578382816116d9576116d961233a565b04925050506103d9565b83811061171457604051630c740aef60e31b8152600481018790526024810186905260448101859052606401610f71565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f5f836001600160a01b03168360405161179591906125bd565b5f604051808303815f865af19150503d805f81146117ce576040519150601f19603f3d011682016040523d82523d5f602084013e6117d3565b606091505b50915091505f8280156117fe5750815115806117fe5750818060200190518101906117fe91906125c8565b905080158061181557506001600160a01b0385163b155b156118335760405163022e258160e11b815260040160405180910390fd5b5050505050565b600160bf1b67ff000000000000008216156119475767800000000000000082161561186e5768016a09e667f3bcc9090260401c5b67400000000000000082161561188d576801306fe0a31b7152df0260401c5b6720000000000000008216156118ac576801172b83c7d517adce0260401c5b6710000000000000008216156118cb5768010b5586cf9890f62a0260401c5b6708000000000000008216156118ea576801059b0d31585743ae0260401c5b67040000000000000082161561190957680102c9a3e778060ee70260401c5b6702000000000000008216156119285768010163da9fb33356d80260401c5b67010000000000000082161561194757680100b1afa5abcbed610260401c5b66ff000000000000821615611a465766800000000000008216156119745768010058c86da1c09ea20260401c5b6640000000000000821615611992576801002c605e2e8cec500260401c5b66200000000000008216156119b057680100162f3904051fa10260401c5b66100000000000008216156119ce576801000b175effdc76ba0260401c5b66080000000000008216156119ec57680100058ba01fb9f96d0260401c5b6604000000000000821615611a0a5768010002c5cc37da94920260401c5b6602000000000000821615611a28576801000162e525ee05470260401c5b6601000000000000821615611a465768010000b17255775c040260401c5b65ff0000000000821615611b3c5765800000000000821615611a71576801000058b91b5bc9ae0260401c5b65400000000000821615611a8e57680100002c5c89d5ec6d0260401c5b65200000000000821615611aab5768010000162e43f4f8310260401c5b65100000000000821615611ac857680100000b1721bcfc9a0260401c5b65080000000000821615611ae55768010000058b90cf1e6e0260401c5b65040000000000821615611b02576801000002c5c863b73f0260401c5b65020000000000821615611b1f57680100000162e430e5a20260401c5b65010000000000821615611b3c576801000000b1721835510260401c5b64ff00000000821615611c2957648000000000821615611b6557680100000058b90c0b490260401c5b644000000000821615611b815768010000002c5c8601cc0260401c5b642000000000821615611b9d576801000000162e42fff00260401c5b641000000000821615611bb95768010000000b17217fbb0260401c5b640800000000821615611bd5576801000000058b90bfce0260401c5b640400000000821615611bf157680100000002c5c85fe30260401c5b640200000000821615611c0d5768010000000162e42ff10260401c5b640100000000821615611c2957680100000000b17217f80260401c5b63ff000000821615611d0d576380000000821615611c505768010000000058b90bfc0260401c5b6340000000821615611c6b576801000000002c5c85fe0260401c5b6320000000821615611c8657680100000000162e42ff0260401c5b6310000000821615611ca1576801000000000b17217f0260401c5b6308000000821615611cbc57680100000000058b90c00260401c5b6304000000821615611cd75768010000000002c5c8600260401c5b6302000000821615611cf2576801000000000162e4300260401c5b6301000000821615611d0d5768010000000000b172180260401c5b62ff0000821615611de85762800000821615611d32576801000000000058b90c0260401c5b62400000821615611d4c57680100000000002c5c860260401c5b62200000821615611d665768010000000000162e430260401c5b62100000821615611d8057680100000000000b17210260401c5b62080000821615611d9a5768010000000000058b910260401c5b62040000821615611db4576801000000000002c5c80260401c5b62020000821615611dce57680100000000000162e40260401c5b62010000821615611de8576801000000000000b1720260401c5b61ff00821615611eba57618000821615611e0b57680100000000000058b90260401c5b614000821615611e245768010000000000002c5d0260401c5b612000821615611e3d576801000000000000162e0260401c5b611000821615611e565768010000000000000b170260401c5b610800821615611e6f576801000000000000058c0260401c5b610400821615611e8857680100000000000002c60260401c5b610200821615611ea157680100000000000001630260401c5b610100821615611eba57680100000000000000b10260401c5b60ff821615611f83576080821615611edb57680100000000000000590260401c5b6040821615611ef3576801000000000000002c0260401c5b6020821615611f0b57680100000000000000160260401c5b6010821615611f23576801000000000000000b0260401c5b6008821615611f3b57680100000000000000060260401c5b6004821615611f5357680100000000000000030260401c5b6002821615611f6b57680100000000000000010260401c5b6001821615611f8357680100000000000000010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b60405180608001604052805f63ffffffff168152602001611fcc60405180604001604052805f81526020015f81525090565b8152606060208201525f60409091015290565b5f60208284031215611fef575f5ffd5b5035919050565b634e487b7160e01b5f52602160045260245ffd5b602081016002831061201e5761201e611ff6565b91905290565b80356001600160a01b03811681146104ea575f5ffd5b5f6020828403121561204a575f5ffd5b6103d982612024565b803563ffffffff811681146104ea575f5ffd5b80356001600160801b03811681146104ea575f5ffd5b5f5f5f6060848603121561208e575f5ffd5b61209784612024565b92506120a560208501612053565b91506120b360408501612066565b90509250925092565b5f5f5f5f5f5f60c087890312156120d1575f5ffd5b6120da87612024565b95506120e860208801612024565b94506120f660408801612053565b9350606087013567ffffffffffffffff811115612111575f5ffd5b87016040818a031215612122575f5ffd5b925061213060808801612066565b915061213e60a08801612066565b90509295509295509295565b5f81518060208401855e5f93019283525090919050565b6001600160f81b031986811682526001600160c01b031986166001830152841660098201525f612194600a83018561214a565b6001600160801b03199390931683525050601001949350505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561062c5761062c6121b0565b67ffffffffffffffff818116838216019081111561062c5761062c6121b0565b8181038181111561062c5761062c6121b0565b67ffffffffffffffff83168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b6001600160801b03818116838216019081111561062c5761062c6121b0565b8035600381106104ea575f5ffd5b604081525f61228b8461226f565b6003811061229b5761229b611ff6565b6040830152602084013536859003601e190181126122b7575f5ffd5b840160208101903567ffffffffffffffff8111156122d3575f5ffd5b8036038213156122e1575f5ffd5b60406060850152806080850152808260a08601375f60a0828601015260a0601f19601f830116850101925050506103d960208301846001600160801b03169052565b808202811582820484141761062c5761062c6121b0565b634e487b7160e01b5f52601260045260245ffd5b5f8261236857634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561237d575f5ffd5b6103d98261226f565b5f5f8335601e1984360301811261239b575f5ffd5b83018035915067ffffffffffffffff8211156123b5575f5ffd5b6020019150368190038213156123c9575f5ffd5b9250929050565b8035602083101561062c575f19602084900360031b1b1692915050565b6001600160f81b031989811682526001600160c01b031989166001830152871660098201525f612420600a83018861214a565b6001600160f81b0319969096168652505060018401929092526001600160801b03199081166021840152166031820152604101949350505050565b6001600160f81b03198b811682526001600160c01b03198b166001830152891660098201525f61248e600a83018a61214a565b6001600160f81b031998909816885250506001600160e01b031994909416600186015260058501929092526001600160801b031990811660258501529081166035840152166045820152605501949350505050565b80356001600160601b03198116906014841015612524576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b6001600160f81b03198b811682526001600160c01b03198b166001830152891660098201525f61255e600a83018a61214a565b6001600160f81b031998909816885250506001600160e01b03199490941660018601526001600160601b03199290921660058501526001600160801b031990811660198501529081166029840152166039820152604901949350505050565b5f6103d9828461214a565b5f602082840312156125d8575f5ffd5b815180151581146103d9575f5ffdfe8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22ea2646970667358221220046dc7d429ea210c611797c7b4d01fa9b6906f8c2a4299f763335c848dfa743864736f6c634300081c003300000000000000", - "storage": {} - }, - "25": { - "address": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570", - "code": "0x608060405260043610610195575f3560e01c8063a98fb355116100e7578063ceb29d6111610087578063e2148f5a11610062578063e2148f5a14610492578063f2fde38b146104b1578063fc299dee146104d0578063fe776c2a146104ef575f5ffd5b8063ceb29d611461042b578063d156b9111461044a578063d4c250081461045e575f5ffd5b8063be6ab6ef116100c2578063be6ab6ef146103ad578063c1a8e2c5146103ce578063c63fd502146103ed578063c968095b1461040c575f5ffd5b8063a98fb35514610337578063a9a899cd14610356578063b526578714610375575f5ffd5b8063715018a6116101525780638da5cb5b1161012d5780638da5cb5b146102c05780638f661996146102dd5780638f8ee552146102f0578063a831570514610318575f5ffd5b8063715018a61461026e57806373fe4ad81461028257806383821e8e146102a1575f5ffd5b80631500cd8d146101995780632fb31ef1146101ba578063303ca956146101f05780633bc28c8c1461020f57806357e443551461022e57806359b005341461024f575b5f5ffd5b3480156101a4575f5ffd5b506101b86101b3366004611eb6565b61051d565b005b3480156101c5575f5ffd5b506067546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101fb575f5ffd5b506101b861020a366004611f18565b610595565b34801561021a575f5ffd5b506101b8610229366004611eb6565b6106be565b348015610239575f5ffd5b5061024261073e565b6040516101e79190611fa6565b34801561025a575f5ffd5b506101b8610269366004611eb6565b61094b565b348015610279575f5ffd5b506101b86109d0565b34801561028d575f5ffd5b506101b861029c366004612068565b6109e3565b3480156102ac575f5ffd5b506101b86102bb36600461213c565b610d73565b3480156102cb575f5ffd5b506033546001600160a01b03166101d3565b6101b86102eb366004612188565b610f9a565b3480156102fb575f5ffd5b506103035f81565b60405163ffffffff90911681526020016101e7565b348015610323575f5ffd5b506101b86103323660046121b9565b61105a565b348015610342575f5ffd5b506101b861035136600461226a565b6110e5565b348015610361575f5ffd5b506101b8610370366004611eb6565b611164565b348015610380575f5ffd5b5061039d61038f366004611eb6565b6001600160a01b0316301490565b60405190151581526020016101e7565b3480156103b8575f5ffd5b506103c16111b4565b6040516101e7919061229b565b3480156103d9575f5ffd5b506101b86103e83660046122e6565b61125c565b3480156103f8575f5ffd5b506101b8610407366004612336565b611328565b348015610417575f5ffd5b506101b86104263660046121b9565b6114d2565b348015610436575f5ffd5b506101b86104453660046121b9565b61152c565b348015610455575f5ffd5b50610242611792565b348015610469575f5ffd5b506101d3610478366004611eb6565b60686020525f90815260409020546001600160a01b031681565b34801561049d575f5ffd5b506101b86104ac366004611eb6565b6117ae565b3480156104bc575f5ffd5b506101b86104cb366004611eb6565b611828565b3480156104db575f5ffd5b506065546101d3906001600160a01b031681565b3480156104fa575f5ffd5b5061039d610509366004611eb6565b60666020525f908152604090205460ff1681565b6105256118a1565b6001600160a01b03811661054c5760405163d92e233d60e01b815260040160405180910390fd5b606780546001600160a01b0319166001600160a01b0383169081179091556040517f6a8a174b559440c4e231f06fda7f0eb644f79306c33292fbb95f7602bef9aaf9905f90a250565b61059d6118fb565b6001600160a01b03831630146105c657604051631280731d60e21b815260040160405180910390fd5b600181146105e75760405163f37f411760e01b815260040160405180910390fd5b5f828282816105f8576105f86123f5565b905060200201602081019061060d919061241c565b63ffffffff16146106315760405163c106a33360e01b815260040160405180910390fd5b6001600160a01b0384165f90815260686020526040812080546001600160a01b03191690558290829081610667576106676123f5565b905060200201602081019061067c919061241c565b63ffffffff16846001600160a01b03167f2638d53da645bac898f1b50bd1d6d2a4d389e3141e209c988488abced5c3c54c60405160405180910390a350505050565b6106c66118a1565b6001600160a01b0381166106ed5760405163d92e233d60e01b815260040160405180910390fd5b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa499ec18d14a183a8ce150f6d1a61fe68e989121c8aa695bafde5305f1eee81c905f90a35050565b6040805180820182523081525f602082018190529151633743aedd60e11b8152606092907f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b031690636e875dba906107a1908590600401612435565b5f60405180830381865afa1580156107bb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107e2919081019061245d565b90505f81516001600160401b038111156107fe576107fe611fb8565b604051908082528060200260200182016040528015610827578160200160208202803683370190505b5090505f805b83518110156108bb575f60685f86848151811061084c5761084c6123f5565b6020908102919091018101516001600160a01b039081168352908201929092526040015f205416905080156108b2578084848151811061088e5761088e6123f5565b6001600160a01b03909216602092830291909101909101526108af8361250a565b92505b5060010161082d565b50808252604080516020810182528381529051631a7611b760e31b815273cf7ed3acca5a467e9e704c703e8d87f634fb0fc99163d3b08db8916109019190600401612522565b5f60405180830381865af415801561091b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610942919081019061257e565b94505050505090565b610953611944565b6001600160a01b03811661097a5760405163d92e233d60e01b815260040160405180910390fd5b335f8181526068602052604080822080546001600160a01b0319166001600160a01b03861690811790915590519092917f03ddab9377727860d18575279a4fb19cf32e3e650ae962f6ce2feaed801cd3af91a350565b6109d86118a1565b6109e15f6119ff565b565b5f54610100900460ff1615808015610a0157505f54600160ff909116105b80610a1a5750303b158015610a1a57505f5460ff166001145b610a825760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015610aa3575f805461ff0019166101001790555b6001600160a01b038516610aca5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038416610af15760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216610b185760405163d92e233d60e01b815260040160405180910390fd5b610b20611a50565b610b29856119ff565b606580546001600160a01b0319166001600160a01b0386169081179091556040515f907fa499ec18d14a183a8ce150f6d1a61fe68e989121c8aa695bafde5305f1eee81c908290a37f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b031663a9821821306040518060a00160405280606d8152602001612fab606d91396040518363ffffffff1660e01b8152600401610bd79291906125f2565b5f604051808303815f87803b158015610bee575f5ffd5b505af1158015610c00573d5f5f3e3d5ffd5b505f925060019150610c0f9050565b604051908082528060200260200182016040528015610c5457816020015b604080518082019091525f815260606020820152815260200190600190039081610c2d5790505b50905060405180604001604052805f63ffffffff16815260200185815250815f81518110610c8457610c846123f5565b6020908102919091010152604051630130fc2760e51b81526001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063261f84e090610cdd9030908590600401612658565b5f604051808303815f87803b158015610cf4575f5ffd5b505af1158015610d06573d5f5f3e3d5ffd5b5050606780546001600160a01b0319166001600160a01b038716179055505081159050610d6c575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610d7b611a7e565b5f805b610d8b60408401846126e7565b9050811015610dd057610da160408401846126e7565b82818110610db157610db16123f5565b9050604002016020013582610dc6919061272c565b9150600101610d7e565b50610e167f0000000000000000000000009a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae82610e066040860160208701611eb6565b6001600160a01b03169190611aa9565b6040805160018082528183019092525f91816020015b610e776040518060c00160405280606081526020015f6001600160a01b03168152602001606081526020015f63ffffffff1681526020015f63ffffffff168152602001606081525090565b815260200190600190039081610e2c579050509050610e958361286e565b815f81518110610ea757610ea76123f5565b6020908102919091018101919091526040805180820182523081525f9281019290925251630ca2989960e01b81527f0000000000000000000000009a9f2ccfde556a7e9ff0848998aa4a0cfd8863ae6001600160a01b031690630ca2989990610f16908490869060040161297c565b5f604051808303815f87803b158015610f2d575f5ffd5b505af1158015610f3f573d5f5f3e3d5ffd5b505050507fb6d94e6419560f5b19430e640113c0926ed3c399cb053a26a2324b5b29f18e8183858060400190610f7591906126e7565b604051610f8c939250918252602082015260400190565b60405180910390a150505050565b610fa26118a1565b5f610fab61073e565b6067549091506001600160a01b031663f2e500b234835f604051908082528060200260200182016040528015610ff557816020015b6060815260200190600190039081610fe05790505b5060405180602001604052805f81525088886040518763ffffffff1660e01b8152600401611027959493929190612ad1565b5f604051808303818588803b15801561103e575f5ffd5b505af1158015611050573d5f5f3e3d5ffd5b5050505050505050565b6110626118a1565b60405163b66bd98960e01b81526001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063b66bd989906110b49030905f9087908790600401612b7b565b5f604051808303815f87803b1580156110cb575f5ffd5b505af11580156110dd573d5f5f3e3d5ffd5b505050505050565b6110ed6118a1565b60405163a982182160e01b81526001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063a98218219061113b90309085906004016125f2565b5f604051808303815f87803b158015611152575f5ffd5b505af1158015610d6c573d5f5f3e3d5ffd5b61116c6118a1565b6001600160a01b0381165f81815260666020526040808220805460ff19169055517fdf2097d1af3ac651476385ff7048eefcbc11072c13100fa1d966effaf2ea3e549190a250565b6040805180820182523081525f6020820152905163105dea1f60e21b8152606091907f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b031690634177a87c90611215908490600401612435565b5f60405180830381865afa15801561122f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112569190810190612be5565b91505090565b6112646118a1565b5f6040518060600160405280856001600160a01b03168152602001306001600160a01b031681526020018484808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152505050915250604051636e3492b560e01b81529091506001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed1690636e3492b590611311908490600401612c74565b5f604051808303815f87803b15801561103e575f5ffd5b6113306118fb565b6001600160a01b038516301461135957604051631280731d60e21b815260040160405180910390fd5b6001831461137a5760405163b1698da560e01b815260040160405180910390fd5b5f8484828161138b5761138b6123f5565b90506020020160208101906113a0919061241c565b63ffffffff16146113c45760405163c106a33360e01b815260040160405180910390fd5b6001600160a01b0386165f9081526066602052604090205460ff166113fc57604051630444d2e160e21b815260040160405180910390fd5b61143a82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611b8b92505050565b6001600160a01b038781165f90815260686020526040812080546001600160a01b031916939092169290921790558490849081611479576114796123f5565b905060200201602081019061148e919061241c565b63ffffffff16866001600160a01b03167f3ed331d6c3431aecc422f169b89a3c24f9e23cef141e10631262a3fc865f513a60405160405180910390a3505050505050565b6114da6118a1565b604051630287f75160e51b81526001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed16906350feea20906110b49030905f9087908790600401612b7b565b611534611a7e565b5f5b81811015611765575f6040518060a0016040528085858581811061155c5761155c6123f5565b905060200281019061156e9190612ce2565b61157c906020810190611eb6565b6001600160a01b031681525f60208201526040018585858181106115a2576115a26123f5565b90506020028101906115b49190612ce2565b6115c2906020810190612d00565b808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050509082525060200185858581811061160a5761160a6123f5565b905060200281019061161c9190612ce2565b61162a906040810190612d00565b808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250505090825250602001858585818110611672576116726123f5565b90506020028101906116849190612ce2565b611692906060810190612d45565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250604051633635205760e01b81529091506001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed16906336352057906117189030908590600401612d87565b5f604051808303815f875af1158015611733573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261175a9190810190612e40565b505050600101611536565b506040517f69e2dc7f4757ef3cbac3a5423ac42ce1938cb3b79c4f35563460926176265ce0905f90a15050565b6040518060a00160405280606d8152602001612fab606d913981565b6117b66118a1565b6001600160a01b0381166117dd5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0381165f81815260666020526040808220805460ff19166001179055517f5045083cd90f33bcbd2689f0152c6fd980a5bc506dff19aed51f534e2a49ecee9190a250565b6118306118a1565b6001600160a01b0381166118955760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a79565b61189e816119ff565b50565b6033546001600160a01b031633146109e15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a79565b336001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed16146109e1576040516323d871a560e01b815260040160405180910390fd5b6040805180820182523081525f602082015290516333869dd160e11b81527f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed6001600160a01b03169063670d3ba2906119a39033908590600401612edd565b602060405180830381865afa1580156119be573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119e29190612f13565b61189e5760405163668191af60e11b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff16611a765760405162461bcd60e51b8152600401610a7990612f32565b6109e1611c02565b6065546001600160a01b031633146109e157604051638e79fdb560e01b815260040160405180910390fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015611af6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b1a9190612f7d565b9050611b858463095ea7b360e01b85611b33868661272c565b6040516001600160a01b039092166024830152604482015260640160408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c31565b50505050565b5f8151601414611bd65760405162461bcd60e51b8152602060048201526016602482015275092dcecc2d8d2c840c2c8c8e4cae6e640d8cadccee8d60531b6044820152606401610a79565b50602081015160601c80611bfd5760405163d92e233d60e01b815260040160405180910390fd5b919050565b5f54610100900460ff16611c285760405162461bcd60e51b8152600401610a7990612f32565b6109e1336119ff565b5f611c85826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611d099092919063ffffffff16565b905080515f1480611ca5575080806020019051810190611ca59190612f13565b611d045760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610a79565b505050565b6060611d1784845f85611d21565b90505b9392505050565b606082471015611d825760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610a79565b5f5f866001600160a01b03168587604051611d9d9190612f94565b5f6040518083038185875af1925050503d805f8114611dd7576040519150601f19603f3d011682016040523d82523d5f602084013e611ddc565b606091505b5091509150611ded87838387611dfa565b925050505b949350505050565b60608315611e685782515f03611e61576001600160a01b0385163b611e615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a79565b5081611df2565b611df28383815115611e7d5781518083602001fd5b8060405162461bcd60e51b8152600401610a799190611fa6565b6001600160a01b038116811461189e575f5ffd5b8035611bfd81611e97565b5f60208284031215611ec6575f5ffd5b8135611d1a81611e97565b5f5f83601f840112611ee1575f5ffd5b5081356001600160401b03811115611ef7575f5ffd5b6020830191508360208260051b8501011115611f11575f5ffd5b9250929050565b5f5f5f5f60608587031215611f2b575f5ffd5b8435611f3681611e97565b93506020850135611f4681611e97565b925060408501356001600160401b03811115611f60575f5ffd5b611f6c87828801611ed1565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611d1a6020830184611f78565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715611fee57611fee611fb8565b60405290565b60405160c081016001600160401b0381118282101715611fee57611fee611fb8565b604051601f8201601f191681016001600160401b038111828210171561203e5761203e611fb8565b604052919050565b5f6001600160401b0382111561205e5761205e611fb8565b5060051b60200190565b5f5f5f5f6080858703121561207b575f5ffd5b843561208681611e97565b9350602085013561209681611e97565b925060408501356001600160401b038111156120b0575f5ffd5b8501601f810187136120c0575f5ffd5b80356120d36120ce82612046565b612016565b8082825260208201915060208360051b8501019250898311156120f4575f5ffd5b6020840193505b8284101561211f57833561210e81611e97565b8252602093840193909101906120fb565b94506121319250505060608601611eab565b905092959194509250565b5f6020828403121561214c575f5ffd5b81356001600160401b03811115612161575f5ffd5b820160c08185031215611d1a575f5ffd5b80356001600160801b0381168114611bfd575f5ffd5b5f5f60408385031215612199575f5ffd5b6121a283612172565b91506121b060208401612172565b90509250929050565b5f5f602083850312156121ca575f5ffd5b82356001600160401b038111156121df575f5ffd5b6121eb85828601611ed1565b90969095509350505050565b5f6001600160401b0382111561220f5761220f611fb8565b50601f01601f191660200190565b5f82601f83011261222c575f5ffd5b813561223a6120ce826121f7565b81815284602083860101111561224e575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f6020828403121561227a575f5ffd5b81356001600160401b0381111561228f575f5ffd5b611df28482850161221d565b602080825282518282018190525f918401906040840190835b818110156122db5783516001600160a01b03168352602093840193909201916001016122b4565b509095945050505050565b5f5f5f604084860312156122f8575f5ffd5b833561230381611e97565b925060208401356001600160401b0381111561231d575f5ffd5b61232986828701611ed1565b9497909650939450505050565b5f5f5f5f5f5f6080878903121561234b575f5ffd5b863561235681611e97565b9550602087013561236681611e97565b945060408701356001600160401b03811115612380575f5ffd5b61238c89828a01611ed1565b90955093505060608701356001600160401b038111156123aa575f5ffd5b8701601f810189136123ba575f5ffd5b80356001600160401b038111156123cf575f5ffd5b8960208284010111156123e0575f5ffd5b60208201935080925050509295509295509295565b634e487b7160e01b5f52603260045260245ffd5b803563ffffffff81168114611bfd575f5ffd5b5f6020828403121561242c575f5ffd5b611d1a82612409565b81516001600160a01b0316815260208083015163ffffffff1690820152604081015b92915050565b5f6020828403121561246d575f5ffd5b81516001600160401b03811115612482575f5ffd5b8201601f81018413612492575f5ffd5b80516124a06120ce82612046565b8082825260208201915060208360051b8501019250868311156124c1575f5ffd5b6020840193505b828410156124ec5783516124db81611e97565b8252602093840193909101906124c8565b9695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161251b5761251b6124f6565b5060010190565b602081525f6040820183516020808501528181518084526060860191506020830193505f92505b808310156125745783516001600160a01b031682526020938401936001939093019290910190612549565b5095945050505050565b5f6020828403121561258e575f5ffd5b81516001600160401b038111156125a3575f5ffd5b8201601f810184136125b3575f5ffd5b80516125c16120ce826121f7565b8181528560208385010111156125d5575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b6001600160a01b03831681526040602082018190525f90611d1790830184611f78565b5f8151808452602084019350602083015f5b8281101561264e5781516001600160a01b0316865260209586019590910190600101612627565b5093949350505050565b5f6040820160018060a01b03851683526040602084015280845180835260608501915060608160051b8601019250602086015f5b828110156126da57605f19878603018452815163ffffffff815116865260208101519050604060208701526126c46040870182612615565b955050602093840193919091019060010161268c565b5092979650505050505050565b5f5f8335601e198436030181126126fc575f5ffd5b8301803591506001600160401b03821115612715575f5ffd5b6020019150600681901b3603821315611f11575f5ffd5b80820180821115612457576124576124f6565b5f82601f83011261274e575f5ffd5b813561275c6120ce82612046565b8082825260208201915060208360061b86010192508583111561277d575f5ffd5b602085015b838110156125745760408188031215612799575f5ffd5b6127a1611fcc565b81356127ac81611e97565b815260208201356bffffffffffffffffffffffff811681146127cc575f5ffd5b6020828101919091529084529290920191604001612782565b5f82601f8301126127f4575f5ffd5b81356128026120ce82612046565b8082825260208201915060208360061b860101925085831115612823575f5ffd5b602085015b83811015612574576040818803121561283f575f5ffd5b612847611fcc565b813561285281611e97565b8152602082810135818301529084529290920191604001612828565b5f60c0823603121561287e575f5ffd5b612886611ff4565b82356001600160401b0381111561289b575f5ffd5b6128a73682860161273f565b8252506128b660208401611eab565b602082015260408301356001600160401b038111156128d3575f5ffd5b6128df368286016127e5565b6040830152506128f160608401612409565b606082015261290260808401612409565b608082015260a08301356001600160401b0381111561291f575f5ffd5b61292b3682860161221d565b60a08301525092915050565b5f8151808452602084019350602083015f5b8281101561264e57815180516001600160a01b031687526020908101518188015260409096019590910190600101612949565b82516001600160a01b0316815260208084015163ffffffff16908201525f606082016060604084015280845180835260808501915060808160051b8601019250602086015f5b828110156126da57868503607f190184528151805160c080885281519088018190526020909101905f9060e08901905b80831015612a3757835180516001600160a01b031683526020908101516bffffffffffffffffffffffff168184015290930192600192909201916040909101906129f2565b5060208401519250612a5460208a01846001600160a01b03169052565b6040840151925088810360408a0152612a6d8184612937565b925050506060820151612a88606089018263ffffffff169052565b506080820151612aa0608089018263ffffffff169052565b5060a0820151915086810360a0880152612aba8183611f78565b9650505060209384019391909101906001016129c2565b60a081525f612ae360a0830188611f78565b828103602084015280875180835260208301915060208160051b84010160208a015f5b83811015612b3857601f19868403018552612b22838351611f78565b6020958601959093509190910190600101612b06565b50508581036040870152612b4c818a611f78565b945050505050612b6760608301856001600160801b03169052565b6001600160801b03831660808301526124ec565b6001600160a01b038516815263ffffffff8416602082015260606040820181905281018290525f8360808301825b85811015612bd9578235612bbc81611e97565b6001600160a01b0316825260209283019290910190600101612ba9565b50979650505050505050565b5f60208284031215612bf5575f5ffd5b81516001600160401b03811115612c0a575f5ffd5b8201601f81018413612c1a575f5ffd5b8051612c286120ce82612046565b8082825260208201915060208360051b850101925086831115612c49575f5ffd5b6020840193505b828410156124ec578351612c6381611e97565b825260209384019390910190612c50565b602080825282516001600160a01b039081168383015283820151166040808401919091528301516060808401528051608084018190525f929190910190829060a08501905b808310156125745763ffffffff8451168252602082019150602084019350600183019250612cb9565b5f8235607e19833603018112612cf6575f5ffd5b9190910192915050565b5f5f8335601e19843603018112612d15575f5ffd5b8301803591506001600160401b03821115612d2e575f5ffd5b6020019150600581901b3603821315611f11575f5ffd5b5f5f8335601e19843603018112612d5a575f5ffd5b8301803591506001600160401b03821115612d73575f5ffd5b602001915036819003821315611f11575f5ffd5b6001600160a01b038381168252604060208084018290528451909216818401529083015163ffffffff16606083015282015160a060808301525f90612dcf60e0840182612615565b6060850151848203603f190160a08601528051808352602091820193505f9291909101905b80831015612e175783518252602082019150602084019350600183019250612df4565b506080860151858203603f190160c08701529250612e358184611f78565b979650505050505050565b5f5f60408385031215612e51575f5ffd5b825160208401519092506001600160401b03811115612e6e575f5ffd5b8301601f81018513612e7e575f5ffd5b8051612e8c6120ce82612046565b8082825260208201915060208360051b850101925087831115612ead575f5ffd5b6020840193505b82841015612ecf578351825260209384019390910190612eb4565b809450505050509250929050565b6001600160a01b038316815260608101611d1a602083018480516001600160a01b0316825260209081015163ffffffff16910152565b5f60208284031215612f23575f5ffd5b81518015158114611d1a575f5ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f60208284031215612f8d575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fe68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f64617461686176656e2d78797a2f64617461686176656e2f726566732f68656164732f6d61696e2f636f6e7472616374732f6465706c6f796d656e74732f6d657461646174612e6a736f6ea2646970667358221220848caaac0696f7f1d3c1a9423af8da01763e34ec5f5ed3f91c36001db2d0cb1b64736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "32": { - "address": "0x998abeb3E57409262aE5b751f60747921B33613E", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x0000000000000000000000000000000000000000000000000000000000000032": "0x00000000000000000000000095401dc811bb5740090279ba06cfa8fcf6113778", - "0x0000000000000000000000000000000000000000000000000000000000000064": "0x00000000000000000000000000000000000000000000d3c21bcecceda1000000", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x0000000000000000000000000000000000000000000000000000000000000065": "0x000000000000000000000000000000000000000000084595161401484a000000", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000f5059a5d33d5853360d16c683c16e67980206f36" - } - }, - "10": { - "address": "0xf5059a5D33d5853360D16C683c16e67980206f36", - "code": "0x608060405234801561000f575f5ffd5b5060043610610187575f3560e01c80637a8b2637116100d9578063c4d66de811610093578063df6fadc11161006e578063df6fadc114610361578063e3dae51c1461037c578063f3e738751461038f578063fabc1cbc146103a2575f5ffd5b8063c4d66de814610328578063ce7c2ac21461033b578063d9caed121461034e575f5ffd5b80637a8b2637146102ad578063886f1195146102c05780638c871019146102e75780638f6a6240146102fa578063a6ab36f21461030d578063ab5921e114610320575f5ffd5b806347e7ef2411610144578063595c6a671161011f578063595c6a67146102655780635ac86ab71461026d5780635c975abb1461029c57806361b01b5d146102a4575f5ffd5b806347e7ef241461022a57806354fd4d501461023d578063553ca5f814610252575f5ffd5b806311c70c9d1461018b578063136439dd146101a05780632495a599146101b357806339b70e38146101e35780633a98ef391461020a57806343fe08b014610221575b5f5ffd5b61019e6101993660046111b1565b6103b5565b005b61019e6101ae3660046111d1565b6103cb565b6032546101c6906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c67f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b61021360335481565b6040519081526020016101da565b61021360645481565b6102136102383660046111fc565b610401565b610245610530565b6040516101da9190611226565b61021361026036600461125b565b610560565b61019e610573565b61028c61027b36600461128b565b6001805460ff9092161b9081161490565b60405190151581526020016101da565b600154610213565b61021360655481565b6102136102bb3660046111d1565b610587565b6101c67f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6102136102f53660046111d1565b6105d0565b61021361030836600461125b565b6105da565b61019e61031b3660046112a6565b6105e7565b6102456106c2565b61019e61033636600461125b565b6106e2565b61021361034936600461125b565b6107a8565b61021361035c3660046112dc565b61083a565b606454606554604080519283526020830191909152016101da565b61021361038a3660046111d1565b61093c565b61021361039d3660046111d1565b610973565b61019e6103b03660046111d1565b61097d565b6103bd6109ea565b6103c78282610a9b565b5050565b6103d3610b3f565b60015481811681146103f85760405163c61dca5d60e01b815260040160405180910390fd5b6103c782610be2565b5f5f61040c81610c1f565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075081614610455576040516348da714f60e01b815260040160405180910390fd5b61045f8484610c55565b6033545f61046f6103e88361132e565b90505f6103e861047d610cac565b610487919061132e565b90505f6104948783611341565b9050806104a18489611354565b6104ab919061136b565b9550855f036104cd57604051630c392ed360e11b815260040160405180910390fd5b6104d7868561132e565b60338190556f4b3b4ca85a86c47a098a223fffffffff101561050c57604051632f14e8a360e11b815260040160405180910390fd5b610525826103e8603354610520919061132e565b610d16565b505050505092915050565b606061055b7f76312e302e300000000000000000000000000000000000000000000000000006610d62565b905090565b5f61056d6102bb836107a8565b92915050565b61057b610b3f565b6105855f19610be2565b565b5f5f6103e8603354610599919061132e565b90505f6103e86105a7610cac565b6105b1919061132e565b9050816105be8583611354565b6105c8919061136b565b949350505050565b5f61056d8261093c565b5f61056d61039d836107a8565b5f54610100900460ff161580801561060557505f54600160ff909116105b8061061e5750303b15801561061e57505f5460ff166001145b6106435760405162461bcd60e51b815260040161063a9061138a565b60405180910390fd5b5f805460ff191660011790558015610664575f805461ff0019166101001790555b61066e8484610a9b565b61067782610d9f565b80156106bc575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b60606040518060800160405280604d815260200161145b604d9139905090565b5f54610100900460ff161580801561070057505f54600160ff909116105b806107195750303b15801561071957505f5460ff166001145b6107355760405162461bcd60e51b815260040161063a9061138a565b5f805460ff191660011790558015610756575f805461ff0019166101001790555b61075f82610d9f565b80156103c7575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15050565b60405163fe243a1760e01b81526001600160a01b0382811660048301523060248301525f917f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075089091169063fe243a1790604401602060405180830381865afa158015610816573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061056d91906113d8565b5f600161084681610c1f565b336001600160a01b037f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb607508161461088f576040516348da714f60e01b815260040160405180910390fd5b61089a858585610eea565b603354808411156108be57604051630b469df360e41b815260040160405180910390fd5b5f6108cb6103e88361132e565b90505f6103e86108d9610cac565b6108e3919061132e565b9050816108f08783611354565b6108fa919061136b565b94506109068684611341565b6033556109266109168683611341565b6103e8603354610520919061132e565b610931888887610f1d565b505050509392505050565b5f5f6103e860335461094e919061132e565b90505f6103e861095c610cac565b610966919061132e565b9050806105be8386611354565b5f61056d82610587565b6109856109ea565b600154801982198116146109ac5760405163c61dca5d60e01b815260040160405180910390fd5b600182905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a46573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6a91906113ef565b6001600160a01b0316336001600160a01b0316146105855760405163794821ff60e01b815260040160405180910390fd5b60645460408051918252602082018490527ff97ed4e083acac67830025ecbc756d8fe847cdbdca4cee3fe1e128e98b54ecb5910160405180910390a160655460408051918252602082018390527f6ab181e0440bfbf4bacdf2e99674735ce6638005490688c5f994f5399353e452910160405180910390a180821115610b345760405163052b07b760e21b815260040160405180910390fd5b606491909155606555565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa158015610ba1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc5919061140a565b61058557604051631d77d47760e21b815260040160405180910390fd5b600181905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b610c34816001805460ff9092161b9081161490565b15610c525760405163840a48d560e01b815260040160405180910390fd5b50565b606454811115610c785760405163052b07b760e21b815260040160405180910390fd5b606554610c83610cac565b1115610ca25760405163d86bae6760e01b815260040160405180910390fd5b6103c78282610f31565b6032546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610cf2573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055b91906113d8565b7fd2494f3479e5da49d386657c292c610b5b01df313d07c62eb0cfa49924a31be881610d4a84670de0b6b3a7640000611354565b610d54919061136b565b60405190815260200161079c565b60605f610d6e83610f5f565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f54610100900460ff16610e095760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161063a565b603280546001600160a01b0319166001600160a01b038316179055610e2d5f610be2565b7f1c540707b00eb5427b6b774fc799d756516a54aee108b64b327acc55af55750760325f9054906101000a90046001600160a01b0316826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e9f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ec39190611429565b604080516001600160a01b03909316835260ff90911660208301520160405180910390a150565b6032546001600160a01b03838116911614610f1857604051630312abdd60e61b815260040160405180910390fd5b505050565b610f186001600160a01b0383168483610f86565b6032546001600160a01b038381169116146103c757604051630312abdd60e61b815260040160405180910390fd5b5f60ff8216601f81111561056d57604051632cd44ac360e21b815260040160405180910390fd5b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180516001600160e01b031663a9059cbb60e01b17905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152610f18928692915f91611015918516908490611094565b905080515f1480611035575080806020019051810190611035919061140a565b610f185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161063a565b60606105c884845f85855f5f866001600160a01b031685876040516110b99190611444565b5f6040518083038185875af1925050503d805f81146110f3576040519150601f19603f3d011682016040523d82523d5f602084013e6110f8565b606091505b509150915061110987838387611114565b979650505050505050565b606083156111825782515f0361117b576001600160a01b0385163b61117b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161063a565b50816105c8565b6105c883838151156111975781518083602001fd5b8060405162461bcd60e51b815260040161063a9190611226565b5f5f604083850312156111c2575f5ffd5b50508035926020909101359150565b5f602082840312156111e1575f5ffd5b5035919050565b6001600160a01b0381168114610c52575f5ffd5b5f5f6040838503121561120d575f5ffd5b8235611218816111e8565b946020939093013593505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f6020828403121561126b575f5ffd5b8135611276816111e8565b9392505050565b60ff81168114610c52575f5ffd5b5f6020828403121561129b575f5ffd5b81356112768161127d565b5f5f5f606084860312156112b8575f5ffd5b833592506020840135915060408401356112d1816111e8565b809150509250925092565b5f5f5f606084860312156112ee575f5ffd5b83356112f9816111e8565b92506020840135611309816111e8565b929592945050506040919091013590565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561056d5761056d61131a565b8181038181111561056d5761056d61131a565b808202811582820484141761056d5761056d61131a565b5f8261138557634e487b7160e01b5f52601260045260245ffd5b500490565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b5f602082840312156113e8575f5ffd5b5051919050565b5f602082840312156113ff575f5ffd5b8151611276816111e8565b5f6020828403121561141a575f5ffd5b81518015158114611276575f5ffd5b5f60208284031215611439575f5ffd5b81516112768161127d565b5f82518060208501845e5f92019182525091905056fe4261736520537472617465677920696d706c656d656e746174696f6e20746f20696e68657269742066726f6d20666f72206d6f726520636f6d706c657820696d706c656d656e746174696f6e73a2646970667358221220bfdf80ca4b361e8018a5f82c2bf79ca0703b2a580a1928bf0168143ae266103964736f6c634300081c0033000000000000000000", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "40": { - "address": "0xc5a5C42992dECbae36851359345FE25997F5C42d", - "code": "0x608060405234801561000f575f5ffd5b50600436106102ff575f3560e01c8063670d3ba211610195578063b2447af7116100e4578063db4df7611161009e578063f231bd0811610079578063f231bd08146107f7578063f605ce081461080a578063fabc1cbc1461081d578063fe4b84df14610830575f5ffd5b8063db4df76114610796578063dc2af692146107bd578063df5cf723146107d0575f5ffd5b8063b2447af714610708578063b66bd9891461071b578063b9fbaed11461072e578063ba1a84e51461075d578063c221d8ae14610770578063d3d96ff414610783575f5ffd5b8063886f11951161014f578063952899ee1161012a578063952899ee146106bc578063a9333ec8146106cf578063a9821821146106e2578063adc2e3d9146106f5575f5ffd5b8063886f1195146106625780638ce648541461068957806394d7d00c146106a9575f5ffd5b8063670d3ba2146105c45780636cfb4481146105d75780636e3492b5146106025780636e875dba1461061557806379ae50cd146106285780637bc1ef611461063b575f5ffd5b806340120dab1161025157806350feea201161020b57806356c483e6116101e657806356c483e61461057e578063595c6a67146105915780635ac86ab7146105995780635c975abb146105bc575f5ffd5b806350feea2014610543578063547afb871461055657806354fd4d5014610569575f5ffd5b806340120dab146104875780634177a87c146104a85780634657e26a146104c85780634a10ffe5146104ef5780634b5046ef1461050f5780634cfd293914610522575f5ffd5b8063261f84e0116102bc5780632bab2c4a116102975780632bab2c4a1461042d578063304c10cd1461044057806332a879e4146104535780633635205714610466575f5ffd5b8063261f84e0146103be5780632981eb77146103d15780632b453a9a1461040d575f5ffd5b80630f3df50e1461030357806310e1b9b8146103335780631352c3e614610353578063136439dd1461037657806315fe50281461038b578063260dc758146103ab575b5f5ffd5b610316610311366004614bf0565b610843565b6040516001600160a01b0390911681526020015b60405180910390f35b610346610341366004614c0a565b610884565b60405161032a9190614c51565b610366610361366004614c84565b6108bd565b604051901515815260200161032a565b610389610384366004614cb8565b610938565b005b61039e610399366004614ccf565b610972565b60405161032a9190614d4d565b6103666103b9366004614bf0565b610a89565b6103896103cc366004614d9f565b610aba565b6103f87f000000000000000000000000000000000000000000000000000000000000003281565b60405163ffffffff909116815260200161032a565b61042061041b366004614e84565b610b63565b60405161032a9190614f27565b61042061043b366004614f8a565b610b79565b61031661044e366004614ccf565b610c18565b61038961046136600461500e565b610c47565b61047961047436600461508e565b610d8e565b60405161032a9291906150e0565b61049a6104953660046150f8565b610ed1565b60405161032a929190615185565b6104bb6104b6366004614bf0565b61104c565b60405161032a91906151e2565b6103167f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c81565b6105026104fd3660046151f4565b611070565b60405161032a9190615237565b61038961051d36600461500e565b611118565b610535610530366004614bf0565b6111ab565b60405190815260200161032a565b610389610551366004615282565b6111cd565b6105026105643660046152e0565b6112be565b610571611366565b60405161032a9190615322565b61038961058c366004615357565b611396565b61038961149b565b6103666105a7366004615381565b606654600160ff9092169190911b9081161490565b606654610535565b6103666105d2366004614c84565b6114af565b6105ea6105e53660046150f8565b6114db565b6040516001600160401b03909116815260200161032a565b6103896106103660046153b7565b6114f0565b6104bb610623366004614bf0565b6118b3565b61039e610636366004614ccf565b6118c4565b6103f87f000000000000000000000000000000000000000000000000000000000000004b81565b6103167f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b61069c6106973660046153e8565b61199e565b60405161032a919061542b565b6105026106b736600461543d565b611a5a565b6103896106ca366004615498565b611b46565b6105ea6106dd3660046150f8565b611fe7565b6103896106f0366004615641565b612016565b6103896107033660046156bf565b6120c8565b610535610716366004614bf0565b612411565b610389610729366004615282565b612433565b61074161073c366004614ccf565b61258d565b60408051921515835263ffffffff90911660208301520161032a565b61053561076b366004614ccf565b612627565b6104bb61077e366004614c84565b612647565b6103896107913660046150f8565b612670565b6103167f000000000000000000000000c6e7df5e7b4f2a278906862b61205850344d4e7d81565b6103666107cb366004614ccf565b61279d565b6103167f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b610366610805366004614bf0565b6127d0565b6105ea6108183660046150f8565b6127ef565b61038961082b366004614cb8565b6127fb565b61038961083e366004614cb8565b612868565b5f5f60a65f61085185612979565b815260208101919091526040015f20546001600160a01b031690508015610878578061087d565b620e16e45b9392505050565b604080516060810182525f80825260208201819052918101829052906108b3856108ad86612979565b856129dc565b9695505050505050565b6001600160a01b0382165f908152609e602052604081208190816108e085612979565b815260208082019290925260409081015f2081518083019092525460ff8116151580835261010090910463ffffffff169282019290925291508061092e5750806020015163ffffffff164311155b9150505b92915050565b610940612b48565b60665481811681146109655760405163c61dca5d60e01b815260040160405180910390fd5b61096e82612beb565b5050565b6001600160a01b0381165f908152609d602052604081206060919061099690612c28565b90505f816001600160401b038111156109b1576109b1614b00565b6040519080825280602002602001820160405280156109f557816020015b604080518082019091525f80825260208201528152602001906001900390816109cf5790505b5090505f5b82811015610a81576001600160a01b0385165f908152609d60205260409020610a5c90610a279083612c31565b604080518082019091525f80825260208201525060408051808201909152606082901c815263ffffffff909116602082015290565b828281518110610a6e57610a6e615701565b60209081029190910101526001016109fa565b509392505050565b60208082015182516001600160a01b03165f9081526098909252604082206109329163ffffffff90811690612c3c16565b82610ac481612c53565b610ae15760405163932d94f760e01b815260040160405180910390fd5b6001600160a01b0384165f90815260a4602052604090205460ff16610b19576040516348f7dbb960e01b815260040160405180910390fd5b5f5b82811015610b5c57610b5485858584818110610b3957610b39615701565b9050602002810190610b4b9190615715565b620e16e4612cfd565b600101610b1b565b5050505050565b6060610b7184848443612eb1565b949350505050565b6060610b8785858585612eb1565b90505f5b8451811015610c0f57610bb7858281518110610ba957610ba9615701565b6020026020010151876108bd565b610c07575f5b8451811015610c05575f838381518110610bd957610bd9615701565b60200260200101518281518110610bf257610bf2615701565b6020908102919091010152600101610bbd565b505b600101610b8b565b50949350505050565b6001600160a01b038082165f908152609760205260408120549091168015610c40578061087d565b5090919050565b84610c5181612c53565b610c6e5760405163932d94f760e01b815260040160405180910390fd5b838214610c8e576040516343714afd60e01b815260040160405180910390fd5b6001600160a01b0386165f90815260a4602052604090205460ff16610cc6576040516348f7dbb960e01b815260040160405180910390fd5b5f5b84811015610d85575f848483818110610ce357610ce3615701565b9050602002016020810190610cf89190614ccf565b90506001600160a01b038116610d21576040516339b190bb60e11b815260040160405180910390fd5b620e16e3196001600160a01b03821601610d4e576040516364be1a3f60e11b815260040160405180910390fd5b610d7c88888885818110610d6457610d64615701565b9050602002810190610d769190615715565b83612cfd565b50600101610cc8565b50505050505050565b5f60606001610d9c8161319e565b84610da681612c53565b610dc35760405163932d94f760e01b815260040160405180910390fd5b5f6040518060400160405280886001600160a01b03168152602001876020016020810190610df19190615733565b63ffffffff1690529050610e08606087018761574c565b9050610e17604088018861574c565b905014610e37576040516343714afd60e01b815260040160405180910390fd5b60208082015182516001600160a01b03165f90815260989092526040909120610e699163ffffffff90811690612c3c16565b610e8657604051631fb1705560e21b815260040160405180910390fd5b610e9c610e966020880188614ccf565b826108bd565b610eb95760405163ebbff49760e01b815260040160405180910390fd5b610ec386826131cc565b945094505050509250929050565b6001600160a01b0382165f908152609d602052604081206060918291610ef690612c28565b90505f816001600160401b03811115610f1157610f11614b00565b604051908082528060200260200182016040528015610f5557816020015b604080518082019091525f8082526020820152815260200190600190039081610f2f5790505b5090505f826001600160401b03811115610f7157610f71614b00565b604051908082528060200260200182016040528015610fba57816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610f8f5790505b5090505f5b8381101561103d576001600160a01b0388165f908152609d60205260408120610fec90610a279084612c31565b90508084838151811061100157611001615701565b602002602001018190525061101789828a610884565b83838151811061102957611029615701565b602090810291909101015250600101610fbf565b509093509150505b9250929050565b60605f61087d60995f61105e86612979565b81526020019081526020015f2061390c565b60605f83516001600160401b0381111561108c5761108c614b00565b6040519080825280602002602001820160405280156110b5578160200160208202803683370190505b5090505f5b8451811015610a81576110e68582815181106110d8576110d8615701565b602002602001015185611fe7565b8282815181106110f8576110f8615701565b6001600160401b03909216602092830291909101909101526001016110ba565b5f6111228161319e565b838214611142576040516343714afd60e01b815260040160405180910390fd5b5f5b84811015610d85576111a38787878481811061116257611162615701565b90506020020160208101906111779190614ccf565b86868581811061118957611189615701565b905060200201602081019061119e9190615791565b613918565b600101611144565b5f60a55f6111b884612979565b81526020019081526020015f20549050919050565b836111d781612c53565b6111f45760405163932d94f760e01b815260040160405180910390fd5b6040805180820182526001600160a01b03871680825263ffffffff80881660208085018290525f938452609890529390912091926112339291612c3c16565b61125057604051631fb1705560e21b815260040160405180910390fd5b5f5b83811015610d85576112b68286868481811061127057611270615701565b90506020020160208101906112859190614ccf565b6112b160405180604001604052808c6001600160a01b031681526020018b63ffffffff168152506127d0565b613a1c565b600101611252565b60605f82516001600160401b038111156112da576112da614b00565b604051908082528060200260200182016040528015611303578160200160208202803683370190505b5090505f5b8351811015610a81576113348585838151811061132757611327615701565b6020026020010151611fe7565b82828151811061134657611346615701565b6001600160401b0390921660209283029190910190910152600101611308565b60606113917f76312e302e300000000000000000000000000000000000000000000000000006613afc565b905090565b336001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821614611491576113cf82612c53565b6113ec576040516348f5c3ed60e01b815260040160405180910390fd5b6040516336b87bd760e11b81526001600160a01b0383811660048301527f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821690636d70f7ae90602401602060405180830381865afa158015611450573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061147491906157b2565b6114915760405163ccea9e6f60e01b815260040160405180910390fd5b61096e8282613b39565b6114a3612b48565b6114ad5f19612beb565b565b5f61087d83609a5f6114c086612979565b81526020019081526020015f20613ce590919063ffffffff16565b5f5f6114e78484613d06565b95945050505050565b60026114fb8161319e565b61151061150b6020840184614ccf565b612c53565b80611529575061152961150b6040840160208501614ccf565b611546576040516348f5c3ed60e01b815260040160405180910390fd5b5f5b611555604084018461574c565b9050811015611817575f604051806040016040528085602001602081019061157d9190614ccf565b6001600160a01b03168152602001611598604087018761574c565b858181106115a8576115a8615701565b90506020020160208101906115bd9190615733565b63ffffffff16815250905061160a816020015163ffffffff1660985f8760200160208101906115ec9190614ccf565b6001600160a01b0316815260208101919091526040015f2090612c3c565b61162757604051631fb1705560e21b815260040160405180910390fd5b609e5f6116376020870187614ccf565b6001600160a01b03166001600160a01b031681526020019081526020015f205f61166083612979565b815260208101919091526040015f205460ff16611690576040516325131d4f60e01b815260040160405180910390fd5b6116ca61169c82612979565b609c5f6116ac6020890189614ccf565b6001600160a01b0316815260208101919091526040015f2090613e75565b506117026116db6020860186614ccf565b609a5f6116e785612979565b81526020019081526020015f20613e8090919063ffffffff16565b506117106020850185614ccf565b6001600160a01b03167fad34c3070be1dffbcaa499d000ba2b8d9848aefcac3059df245dd95c4ece14fe8260405161174891906157d1565b60405180910390a2604080518082019091525f81526020810161178b7f0000000000000000000000000000000000000000000000000000000000000032436157f3565b63ffffffff169052609e5f6117a36020880188614ccf565b6001600160a01b03166001600160a01b031681526020019081526020015f205f6117cc84612979565b81526020808201929092526040015f2082518154939092015163ffffffff166101000264ffffffff00199215159290921664ffffffffff199093169290921717905550600101611548565b5061182b61044e6040840160208501614ccf565b6001600160a01b031663303ca9566118466020850185614ccf565b6118566040860160208701614ccf565b611863604087018761574c565b6040518563ffffffff1660e01b81526004016118829493929190615848565b5f604051808303815f87803b158015611899575f5ffd5b505af11580156118ab573d5f5f3e3d5ffd5b505050505050565b6060610932609a5f61105e85612979565b6001600160a01b0381165f908152609c60205260408120606091906118e890612c28565b90505f816001600160401b0381111561190357611903614b00565b60405190808252806020026020018201604052801561194757816020015b604080518082019091525f80825260208201528152602001906001900390816119215790505b5090505f5b82811015610a81576001600160a01b0385165f908152609c6020526040902061197990610a279083612c31565b82828151811061198b5761198b615701565b602090810291909101015260010161194c565b60605f84516001600160401b038111156119ba576119ba614b00565b604051908082528060200260200182016040528015611a0357816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816119d85790505b5090505f5b8551811015610c0f57611a35868281518110611a2657611a26615701565b60200260200101518686610884565b828281518110611a4757611a47615701565b6020908102919091010152600101611a08565b60605f83516001600160401b03811115611a7657611a76614b00565b604051908082528060200260200182016040528015611a9f578160200160208202803683370190505b5090505f5b8451811015610c0f576001600160a01b0386165f90815260a1602052604081208651611b1492879291899086908110611adf57611adf615701565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20613e9490919063ffffffff16565b828281518110611b2657611b26615701565b6001600160401b0390921660209283029190910190910152600101611aa4565b5f611b508161319e565b611b5983612c53565b611b76576040516348f5c3ed60e01b815260040160405180910390fd5b5f5f5f611b828661258d565b9150915081611ba45760405163fa55fc8160e01b815260040160405180910390fd5b91505f90505b8351811015610b5c57838181518110611bc557611bc5615701565b60200260200101516040015151848281518110611be457611be4615701565b6020026020010151602001515114611c0f576040516343714afd60e01b815260040160405180910390fd5b5f848281518110611c2257611c22615701565b602090810291909101810151518082015181516001600160a01b03165f90815260989093526040909220909250611c629163ffffffff90811690612c3c16565b611c7f57604051631fb1705560e21b815260040160405180910390fd5b5f611c8a87836108bd565b90505f5b868481518110611ca057611ca0615701565b60200260200101516020015151811015611fdc575f878581518110611cc757611cc7615701565b6020026020010151602001518281518110611ce457611ce4615701565b60200260200101519050611cfb898261ffff613918565b5f5f611d0a8b6108ad88612979565b91509150806040015163ffffffff165f14611d3857604051630d8fcbe360e41b815260040160405180910390fd5b5f611d4587858489613ea8565b9050611d8a825f01518c8a81518110611d6057611d60615701565b6020026020010151604001518781518110611d7d57611d7d615701565b6020026020010151613ede565b600f0b602083018190525f03611db357604051634606179360e11b815260040160405180910390fd5b5f8260200151600f0b1215611ef7578015611e7957611e34611dd488612979565b6001600160a01b03808f165f90815260a360209081526040808320938a16835292905220908154600160801b90819004600f0b5f818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b611e5e7f0000000000000000000000000000000000000000000000000000000000000032436157f3565b611e699060016157f3565b63ffffffff166040830152611f64565b611e8b83602001518360200151613ef5565b6001600160401b031660208401528a518b9089908110611ead57611ead615701565b6020026020010151604001518581518110611eca57611eca615701565b6020908102919091018101516001600160401b031683525f9083015263ffffffff43166040830152611f64565b5f8260200151600f0b1315611f6457611f1883602001518360200151613ef5565b6001600160401b039081166020850181905284519091161015611f4e57604051636c9be0bf60e01b815260040160405180910390fd5b611f5889436157f3565b63ffffffff1660408301525b611f798c611f7189612979565b868686613f14565b7f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd8c8886611fae865f01518760200151613ef5565b8660400151604051611fc4959493929190615874565b60405180910390a1505060019092019150611c8e9050565b505050600101611baa565b6001600160a01b038083165f90815260a160209081526040808320938516835292905290812061087d9061414c565b8261202081612c53565b61203d5760405163932d94f760e01b815260040160405180910390fd5b6001600160a01b0384165f90815260a4602052604090205460ff1661207f576001600160a01b0384165f90815260a460205260409020805460ff191660011790555b836001600160a01b03167fa89c1dc243d8908a96dd84944bcc97d6bc6ac00dd78e20621576be6a3c94371384846040516120ba9291906158ed565b60405180910390a250505050565b60026120d38161319e565b826120dd81612c53565b6120fa5760405163932d94f760e01b815260040160405180910390fd5b6040516336b87bd760e11b81526001600160a01b0385811660048301527f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821690636d70f7ae90602401602060405180830381865afa15801561215e573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061218291906157b2565b61219f5760405163ccea9e6f60e01b815260040160405180910390fd5b5f5b6121ae602085018561574c565b905081101561237657604080518082019091525f90806121d16020880188614ccf565b6001600160a01b031681526020018680602001906121ef919061574c565b858181106121ff576121ff615701565b90506020020160208101906122149190615733565b63ffffffff90811690915260208083015183516001600160a01b03165f90815260989092526040909120929350612250929190811690612c3c16565b61226d57604051631fb1705560e21b815260040160405180910390fd5b61227786826108bd565b1561229557604051636c6c6e2760e11b815260040160405180910390fd5b6122be6122a182612979565b6001600160a01b0388165f908152609c602052604090209061415f565b506122ea86609a5f6122cf85612979565b81526020019081526020015f2061416a90919063ffffffff16565b50856001600160a01b03167f43232edf9071753d2321e5fa7e018363ee248e5f2142e6c08edd3265bfb4895e8260405161232491906157d1565b60405180910390a26001600160a01b0386165f908152609e6020526040812060019161234f84612979565b815260208101919091526040015f20805460ff1916911515919091179055506001016121a1565b5061238761044e6020850185614ccf565b6001600160a01b031663c63fd502856123a36020870187614ccf565b6123b0602088018861574c565b6123bd60408a018a615900565b6040518763ffffffff1660e01b81526004016123de96959493929190615942565b5f604051808303815f87803b1580156123f5575f5ffd5b505af1158015612407573d5f5f3e3d5ffd5b5050505050505050565b5f610932609a5f61242185612979565b81526020019081526020015f20612c28565b8361243d81612c53565b61245a5760405163932d94f760e01b815260040160405180910390fd5b6040805180820182526001600160a01b03871680825263ffffffff80881660208085018290525f938452609890529390912091926124999291612c3c16565b6124b657604051631fb1705560e21b815260040160405180910390fd5b5f6124c082612979565b90505f5b84811015612407576125098686838181106124e1576124e1615701565b90506020020160208101906124f69190614ccf565b5f84815260996020526040902090613e80565b612526576040516331bc342760e11b815260040160405180910390fd5b7f7b4b073d80dcac55a11177d8459ad9f664ceeb91f71f27167bb14f8152a7eeee8387878481811061255a5761255a615701565b905060200201602081019061256f9190614ccf565b60405161257d92919061598e565b60405180910390a16001016124c4565b6001600160a01b0381165f908152609b602090815260408083208151608081018352905463ffffffff80821680845260ff600160201b8404161515958401869052650100000000008304821694840194909452600160481b90910416606082018190528493919291901580159061260e5750826060015163ffffffff164310155b1561261d575050604081015160015b9590945092505050565b6001600160a01b0381165f90815260986020526040812061093290612c28565b6001600160a01b0382165f908152609f602052604081206060919061092e908261105e86612979565b8161267a81612c53565b6126975760405163932d94f760e01b815260040160405180910390fd5b60405163b526578760e01b81526001600160a01b03848116600483015283169063b526578790602401602060405180830381865afa1580156126db573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ff91906157b2565b61271c57604051631d0b13c160e31b815260040160405180910390fd5b6001600160a01b038381165f90815260976020526040902080546001600160a01b0319169184169190911790557f2ae945c40c44dc0ec263f95609c3fdc6952e0aefa22d6374e44f2c997acedf858361277481610c18565b604080516001600160a01b039384168152929091166020830152015b60405180910390a1505050565b5f5f6127a8836118c4565b90505f6127b484610972565b90506127c0848361417e565b80610b715750610b71848261417e565b5f620e16e46127de83610843565b6001600160a01b0316141592915050565b5f5f610c0f8484613d06565b6128036141f6565b6066548019821981161461282a5760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b5f54610100900460ff161580801561288657505f54600160ff909116105b8061289f5750303b15801561289f57505f5460ff166001145b6129075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015612928575f805461ff0019166101001790555b61293182612beb565b801561096e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b5f815f0151826020015163ffffffff166040516020016129c492919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b604051602081830303815290604052610932906159b4565b6040805180820182525f80825260208083018290528351606081018552828152808201839052808501839052845180860186526001600160a01b03898116855260a1845286852090881685529092529382209293928190612a3c9061414c565b6001600160401b0390811682526001600160a01b038981165f81815260a260209081526040808320948c168084529482528083205486169682019690965291815260a082528481208b8252825284812092815291815290839020835160608101855290549283168152600160401b8304600f0b91810191909152600160c01b90910463ffffffff16918101829052919250431015612ade579092509050612b40565b612aef815f01518260200151613ef5565b6001600160401b0316815260208101515f600f9190910b1215612b2d57612b1e82602001518260200151613ef5565b6001600160401b031660208301525b5f60408201819052602082015290925090505b935093915050565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa158015612baa573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bce91906157b2565b6114ad57604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b5f610932825490565b5f61087d83836142a7565b5f818152600183016020526040812054151561087d565b604051631beb2b9760e31b81526001600160a01b0382811660048301523360248301523060448301525f80356001600160e01b0319166064840152917f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c9091169063df595cb8906084016020604051808303815f875af1158015612cd9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061093291906157b2565b5f6040518060400160405280856001600160a01b03168152602001845f016020810190612d2a9190615733565b63ffffffff168152509050612d74816020015163ffffffff1660985f876001600160a01b03166001600160a01b031681526020019081526020015f2061415f90919063ffffffff16565b612d9157604051631fb1705560e21b815260040160405180910390fd5b7f31629285ead2335ae0933f86ed2ae63321f7af77b4e6eaabc42c057880977e6c81604051612dc091906157d1565b60405180910390a16001600160a01b038216620e16e414801590612e55578260a65f612deb85612979565b81526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507f90a6fa2a9b79b910872ebca540cf3bd8be827f586e6420c30d8836e30012907e8284604051612e4c92919061598e565b60405180910390a15b5f5b612e64602086018661574c565b90508110156118ab57612ea983612e7e602088018861574c565b84818110612e8e57612e8e615701565b9050602002016020810190612ea39190614ccf565b84613a1c565b600101612e57565b606083516001600160401b03811115612ecc57612ecc614b00565b604051908082528060200260200182016040528015612eff57816020015b6060815260200190600190039081612eea5790505b5090505f7f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd826001600160a01b031663f0e0e67686866040518363ffffffff1660e01b8152600401612f519291906159d7565b5f60405180830381865afa158015612f6b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612f9291908101906159fb565b90505f5b8551811015613194575f868281518110612fb257612fb2615701565b6020026020010151905085516001600160401b03811115612fd557612fd5614b00565b604051908082528060200260200182016040528015612ffe578160200160208202803683370190505b5084838151811061301157613011615701565b60209081029190910101525f5b865181101561318a575f87828151811061303a5761303a615701565b6020908102919091018101516001600160a01b038086165f90815260a18452604080822092841682529190935282209092506130759061414c565b9050806001600160401b03165f0361308e575050613182565b5f61309a858d85610884565b90508863ffffffff16816040015163ffffffff16111580156130c257505f8160200151600f0b125b156130e4576130d8815f01518260200151613ef5565b6001600160401b031681525b80515f906130ff906001600160401b039081169085166142cd565b90506131468189898151811061311757613117615701565b6020026020010151878151811061313057613130615701565b60200260200101516142e190919063ffffffff16565b89888151811061315857613158615701565b6020026020010151868151811061317157613171615701565b602002602001018181525050505050505b60010161301e565b5050600101612f96565b5050949350505050565b606654600160ff83161b908116036131c95760405163840a48d560e01b815260040160405180910390fd5b50565b5f6060816131dd604086018661574c565b90506001600160401b038111156131f6576131f6614b00565b60405190808252806020026020018201604052801561321f578160200160208202803683370190505b50905061322f604086018661574c565b90506001600160401b0381111561324857613248614b00565b604051908082528060200260200182016040528015613271578160200160208202803683370190505b50915060a55f61328086612979565b81526020019081526020015f205f815461329990615b07565b918290555092505f5b6132af604087018761574c565b905081101561389e5780158061334257506132cd604087018761574c565b6132d8600184615b1f565b8181106132e7576132e7615701565b90506020020160208101906132fc9190614ccf565b6001600160a01b0316613312604088018861574c565b8381811061332257613322615701565b90506020020160208101906133379190614ccf565b6001600160a01b0316115b61335f57604051639f1c805360e01b815260040160405180910390fd5b61336c606087018761574c565b8281811061337c5761337c615701565b905060200201355f1080156133bc5750670de0b6b3a76400006133a2606088018861574c565b838181106133b2576133b2615701565b9050602002013511155b6133d957604051631353603160e01b815260040160405180910390fd5b61341a6133e9604088018861574c565b838181106133f9576133f9615701565b905060200201602081019061340e9190614ccf565b60995f6114c089612979565b613437576040516331bc342760e11b815260040160405180910390fd5b5f8061348961344960208a018a614ccf565b61345289612979565b61345f60408c018c61574c565b8781811061346f5761346f615701565b90506020020160208101906134849190614ccf565b6129dc565b805191935091506001600160401b03165f036134a6575050613896565b5f6134e16134b760608b018b61574c565b868181106134c7576134c7615701565b85516001600160401b0316926020909102013590506142f5565b83519091506134fc6001600160401b038084169083166142cd565b86868151811061350e5761350e615701565b60200260200101818152505081835f0181815161352b9190615b32565b6001600160401b0316905250835182908590613548908390615b32565b6001600160401b0316905250602084018051839190613568908390615b32565b6001600160401b031690525060208301515f600f9190910b1215613680575f6135cb61359760608d018d61574c565b888181106135a7576135a7615701565b9050602002013585602001516135bc90615b51565b6001600160801b0316906142f5565b9050806001600160401b0316846020018181516135e89190615b75565b600f0b9052507f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd61361c60208d018d614ccf565b8b61362a60408f018f61574c565b8a81811061363a5761363a615701565b905060200201602081019061364f9190614ccf565b613660885f01518960200151613ef5565b8860400151604051613676959493929190615874565b60405180910390a1505b6136d261369060208c018c614ccf565b6136998b612979565b6136a660408e018e61574c565b898181106136b6576136b6615701565b90506020020160208101906136cb9190614ccf565b8787613f14565b7f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd61370060208c018c614ccf565b8a61370e60408e018e61574c565b8981811061371e5761371e615701565b90506020020160208101906137339190614ccf565b865160405161374794939291904390615874565b60405180910390a161379861375f60208c018c614ccf565b61376c60408d018d61574c565b8881811061377c5761377c615701565b90506020020160208101906137919190614ccf565b865161430b565b6001600160a01b037f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8216635ae679a76137d460208d018d614ccf565b8b8b8e80604001906137e6919061574c565b8b8181106137f6576137f6615701565b905060200201602081019061380b9190614ccf565b89516040516001600160e01b031960e088901b16815261383395949392918991600401615ba2565b6020604051808303815f875af115801561384f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138739190615bf5565b87868151811061388557613885615701565b602002602001018181525050505050505b6001016132a2565b507f80969ad29428d6797ee7aad084f9e4a42a82fc506dcd2ca3b6fb431f85ccebe56138cd6020870187614ccf565b856138db604089018961574c565b856138e960808c018c615900565b6040516138fc9796959493929190615c0c565b60405180910390a1509250929050565b60605f61087d8361438d565b6001600160a01b038381165f90815260a360209081526040808320938616835292905290812054600f81810b600160801b909204900b035b5f8111801561396257508261ffff1682105b15610b5c576001600160a01b038086165f90815260a3602090815260408083209388168352929052908120613996906143e6565b90505f5f6139a58884896129dc565b91509150806040015163ffffffff164310156139c357505050610b5c565b6139d08884898585613f14565b6001600160a01b038089165f90815260a360209081526040808320938b168352929052206139fd90614438565b50613a0785615b07565b9450613a1284615ca2565b9350505050613950565b8015613a9e576001600160a01b03821673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac014801590613a8157507f000000000000000000000000c6e7df5e7b4f2a278906862b61205850344d4e7d6001600160a01b0316826001600160a01b031614155b613a9e57604051632711b74d60e11b815260040160405180910390fd5b613aae8260995f6122cf87612979565b613acb5760405163585cfb2f60e01b815260040160405180910390fd5b7f7ab260fe0af193db5f4986770d831bda4ea46099dc817e8b6716dcae8af8e88b838360405161279092919061598e565b60605f613b08836144b5565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b6001600160a01b0382165f908152609b60209081526040918290208251608081018452905463ffffffff808216835260ff600160201b830416151593830193909352650100000000008104831693820193909352600160481b909204166060820181905215801590613bb55750806060015163ffffffff164310155b15613bcf57604081015163ffffffff168152600160208201525b63ffffffff82166040820152613c057f000000000000000000000000000000000000000000000000000000000000004b436157f3565b613c109060016157f3565b63ffffffff90811660608381019182526001600160a01b0386165f818152609b602090815260409182902087518154838a0151858b01519851928a1664ffffffffff1990921691909117600160201b91151591909102176cffffffffffffffff0000000000191665010000000000978916979097026cffffffff000000000000000000191696909617600160481b968816968702179055815192835294871694820194909452928301919091527f4e85751d6331506c6c62335f207eb31f12a61e570f34f5c17640308785c6d4db9101612790565b6001600160a01b0381165f908152600183016020526040812054151561087d565b6001600160a01b038281165f81815260a2602090815260408083209486168084529482528083205493835260a38252808320948352939052918220546001600160401b039091169190600f81810b600160801b909204900b03815b81811015613e31576001600160a01b038087165f90815260a3602090815260408083209389168352929052908120613d9990836144dc565b6001600160a01b038881165f90815260a0602090815260408083208584528252808320938b16835292815290829020825160608101845290546001600160401b0381168252600160401b8104600f0b92820192909252600160c01b90910463ffffffff16918101829052919250431015613e14575050613e31565b613e22868260200151613ef5565b95505050806001019050613d61565b506001600160a01b038086165f90815260a1602090815260408083209388168352929052208390613e619061414c565b613e6b9190615b32565b9150509250929050565b5f61087d838361454b565b5f61087d836001600160a01b03841661454b565b5f61087d8383670de0b6b3a764000061462e565b5f613eb98460995f6114c089612979565b8015613ec25750815b80156114e757505090516001600160401b031615159392505050565b5f61087d6001600160401b03808516908416615cb7565b5f61087d613f0c836001600160401b038616615b75565b600f0b614683565b6020808301516001600160a01b038088165f90815260a284526040808220928816825291909352909120546001600160401b03908116911614613fda57602082810180516001600160a01b038881165f81815260a286526040808220938a1680835293875290819020805467ffffffffffffffff19166001600160401b0395861617905593518451918252948101919091529216908201527facf9095feb3a370c9cf692421c69ef320d4db5c66e6a7d29c7694eb02364fc559060600160405180910390a15b6001600160a01b038086165f90815260a060209081526040808320888452825280832093871683529281529082902083518154928501519385015163ffffffff16600160c01b0263ffffffff60c01b196001600160801b038616600160401b026001600160c01b03199095166001600160401b03909316929092179390931716919091179055600f0b156140bc576001600160a01b0385165f908152609f602090815260408083208784529091529020614094908461416a565b506001600160a01b0385165f908152609d602052604090206140b6908561415f565b50610b5c565b80516001600160401b03165f03610b5c576001600160a01b0385165f908152609f6020908152604080832087845290915290206140f99084613e80565b506001600160a01b0385165f908152609f60209081526040808320878452909152902061412590612c28565b5f03610b5c576001600160a01b0385165f908152609d602052604090206118ab9085613e75565b5f61093282670de0b6b3a76400006146ee565b5f61087d8383614725565b5f61087d836001600160a01b038416614725565b5f805b82518110156141ed576141ad848483815181106141a0576141a0615701565b60200260200101516108bd565b80156141d657506141d68382815181106141c9576141c9615701565b60200260200101516127d0565b156141e5576001915050610932565b600101614181565b505f9392505050565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015614252573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906142769190615ce4565b6001600160a01b0316336001600160a01b0316146114ad5760405163794821ff60e01b815260040160405180910390fd5b5f825f0182815481106142bc576142bc615701565b905f5260205f200154905092915050565b5f61087d83670de0b6b3a764000084614771565b5f61087d8383670de0b6b3a7640000614771565b5f61087d8383670de0b6b3a76400006001614856565b6001600160a01b038084165f90815260a16020908152604080832093861683529290522061433a9043836148a5565b604080516001600160a01b038086168252841660208201526001600160401b038316918101919091527f1c6458079a41077d003c11faf9bf097e693bd67979e4e6500bac7b29db779b5c90606001612790565b6060815f018054806020026020016040519081016040528092919081815260200182805480156143da57602002820191905f5260205f20905b8154815260200190600101908083116143c6575b50505050509050919050565b5f6144008254600f81810b600160801b909204900b131590565b1561441e57604051631ed9509560e11b815260040160405180910390fd5b508054600f0b5f9081526001909101602052604090205490565b5f6144528254600f81810b600160801b909204900b131590565b1561447057604051631ed9509560e11b815260040160405180910390fd5b508054600f0b5f818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b5f60ff8216601f81111561093257604051632cd44ac360e21b815260040160405180910390fd5b5f5f6144fe6144ea846148be565b85546144f99190600f0b615cff565b614927565b8454909150600160801b9004600f90810b9082900b1261453157604051632d0483c560e21b815260040160405180910390fd5b600f0b5f9081526001939093016020525050604090205490565b5f8181526001830160205260408120548015614625575f61456d600183615b1f565b85549091505f9061458090600190615b1f565b90508181146145df575f865f01828154811061459e5761459e615701565b905f5260205f200154905080875f0184815481106145be576145be615701565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806145f0576145f0615d26565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610932565b5f915050610932565b82545f908161463f86868385614990565b905080156146795761466386614656600184615b1f565b5f91825260209091200190565b54600160201b90046001600160e01b03166108b3565b5091949350505050565b5f6001600160401b038211156146ea5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084016128fe565b5090565b81545f90801561471d5761470784614656600184615b1f565b54600160201b90046001600160e01b031661092e565b509092915050565b5f81815260018301602052604081205461476a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610932565b505f610932565b5f80805f19858709858702925082811083820303915050805f036147a85783828161479e5761479e615d3a565b049250505061087d565b8084116147ef5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b60448201526064016128fe565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f5f614863868686614771565b9050600183600281111561487957614879615d4e565b14801561489557505f848061489057614890615d3a565b868809115b156114e7576108b3600182615d62565b6148b983836001600160401b0384166149e3565b505050565b5f6001600160ff1b038211156146ea5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016128fe565b80600f81900b811461498b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016128fe565b919050565b5f5b81831015610a81575f6149a58484614ae6565b5f8781526020902090915063ffffffff86169082015463ffffffff1611156149cf578092506149dd565b6149da816001615d62565b93505b50614992565b82548015614a99575f6149fb85614656600185615b1f565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b031660208401529192509085161015614a4d5760405163151b8e3f60e11b815260040160405180910390fd5b805163ffffffff808616911603614a975782614a6e86614656600186615b1f565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790555050505050565b505b506040805180820190915263ffffffff92831681526001600160e01b03918216602080830191825285546001810187555f968752952091519051909216600160201b029190921617910155565b5f614af46002848418615d75565b61087d90848416615d62565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b0381118282101715614b3657614b36614b00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715614b6457614b64614b00565b604052919050565b6001600160a01b03811681146131c9575f5ffd5b803563ffffffff8116811461498b575f5ffd5b5f60408284031215614ba3575f5ffd5b604080519081016001600160401b0381118282101715614bc557614bc5614b00565b6040529050808235614bd681614b6c565b8152614be460208401614b80565b60208201525092915050565b5f60408284031215614c00575f5ffd5b61087d8383614b93565b5f5f5f60808486031215614c1c575f5ffd5b8335614c2781614b6c565b9250614c368560208601614b93565b91506060840135614c4681614b6c565b809150509250925092565b81516001600160401b03168152602080830151600f0b9082015260408083015163ffffffff169082015260608101610932565b5f5f60608385031215614c95575f5ffd5b8235614ca081614b6c565b9150614caf8460208501614b93565b90509250929050565b5f60208284031215614cc8575f5ffd5b5035919050565b5f60208284031215614cdf575f5ffd5b813561087d81614b6c565b80516001600160a01b0316825260209081015163ffffffff16910152565b5f8151808452602084019350602083015f5b82811015614d4357614d2d868351614cea565b6040959095019460209190910190600101614d1a565b5093949350505050565b602081525f61087d6020830184614d08565b5f5f83601f840112614d6f575f5ffd5b5081356001600160401b03811115614d85575f5ffd5b6020830191508360208260051b8501011115611045575f5ffd5b5f5f5f60408486031215614db1575f5ffd5b8335614dbc81614b6c565b925060208401356001600160401b03811115614dd6575f5ffd5b614de286828701614d5f565b9497909650939450505050565b5f6001600160401b03821115614e0757614e07614b00565b5060051b60200190565b5f82601f830112614e20575f5ffd5b8135614e33614e2e82614def565b614b3c565b8082825260208201915060208360051b860101925085831115614e54575f5ffd5b602085015b83811015614e7a578035614e6c81614b6c565b835260209283019201614e59565b5095945050505050565b5f5f5f60808486031215614e96575f5ffd5b614ea08585614b93565b925060408401356001600160401b03811115614eba575f5ffd5b614ec686828701614e11565b92505060608401356001600160401b03811115614ee1575f5ffd5b614eed86828701614e11565b9150509250925092565b5f8151808452602084019350602083015f5b82811015614d43578151865260209586019590910190600101614f09565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015614f7e57603f19878603018452614f69858351614ef7565b94506020938401939190910190600101614f4d565b50929695505050505050565b5f5f5f5f60a08587031215614f9d575f5ffd5b614fa78686614b93565b935060408501356001600160401b03811115614fc1575f5ffd5b614fcd87828801614e11565b93505060608501356001600160401b03811115614fe8575f5ffd5b614ff487828801614e11565b92505061500360808601614b80565b905092959194509250565b5f5f5f5f5f60608688031215615022575f5ffd5b853561502d81614b6c565b945060208601356001600160401b03811115615047575f5ffd5b61505388828901614d5f565b90955093505060408601356001600160401b03811115615071575f5ffd5b61507d88828901614d5f565b969995985093965092949392505050565b5f5f6040838503121561509f575f5ffd5b82356150aa81614b6c565b915060208301356001600160401b038111156150c4575f5ffd5b830160a081860312156150d5575f5ffd5b809150509250929050565b828152604060208201525f610b716040830184614ef7565b5f5f60408385031215615109575f5ffd5b823561511481614b6c565b915060208301356150d581614b6c565b5f8151808452602084019350602083015f5b82811015614d435761516f86835180516001600160401b03168252602080820151600f0b9083015260409081015163ffffffff16910152565b6060959095019460209190910190600101615136565b604081525f6151976040830185614d08565b82810360208401526114e78185615124565b5f8151808452602084019350602083015f5b82811015614d435781516001600160a01b03168652602095860195909101906001016151bb565b602081525f61087d60208301846151a9565b5f5f60408385031215615205575f5ffd5b82356001600160401b0381111561521a575f5ffd5b61522685828601614e11565b92505060208301356150d581614b6c565b602080825282518282018190525f918401906040840190835b818110156152775783516001600160401b0316835260209384019390920191600101615250565b509095945050505050565b5f5f5f5f60608587031215615295575f5ffd5b84356152a081614b6c565b93506152ae60208601614b80565b925060408501356001600160401b038111156152c8575f5ffd5b6152d487828801614d5f565b95989497509550505050565b5f5f604083850312156152f1575f5ffd5b82356152fc81614b6c565b915060208301356001600160401b03811115615316575f5ffd5b613e6b85828601614e11565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215615368575f5ffd5b823561537381614b6c565b9150614caf60208401614b80565b5f60208284031215615391575f5ffd5b813560ff8116811461087d575f5ffd5b5f606082840312156153b1575f5ffd5b50919050565b5f602082840312156153c7575f5ffd5b81356001600160401b038111156153dc575f5ffd5b61092e848285016153a1565b5f5f5f608084860312156153fa575f5ffd5b83356001600160401b0381111561540f575f5ffd5b61541b86828701614e11565b935050614c368560208601614b93565b602081525f61087d6020830184615124565b5f5f5f6060848603121561544f575f5ffd5b833561545a81614b6c565b925060208401356001600160401b03811115615474575f5ffd5b61548086828701614e11565b92505061548f60408501614b80565b90509250925092565b5f5f604083850312156154a9575f5ffd5b82356154b481614b6c565b915060208301356001600160401b038111156154ce575f5ffd5b8301601f810185136154de575f5ffd5b80356154ec614e2e82614def565b8082825260208201915060208360051b85010192508783111561550d575f5ffd5b602084015b838110156156325780356001600160401b0381111561552f575f5ffd5b85016080818b03601f19011215615544575f5ffd5b61554c614b14565b6155598b60208401614b93565b815260608201356001600160401b03811115615573575f5ffd5b6155828c602083860101614e11565b60208301525060808201356001600160401b038111156155a0575f5ffd5b6020818401019250508a601f8301126155b7575f5ffd5b81356155c5614e2e82614def565b8082825260208201915060208360051b86010192508d8311156155e6575f5ffd5b6020850194505b8285101561561c5784356001600160401b038116811461560b575f5ffd5b8252602094850194909101906155ed565b6040840152505084525060209283019201615512565b50809450505050509250929050565b5f5f5f60408486031215615653575f5ffd5b833561565e81614b6c565b925060208401356001600160401b03811115615678575f5ffd5b8401601f81018613615688575f5ffd5b80356001600160401b0381111561569d575f5ffd5b8660208284010111156156ae575f5ffd5b939660209190910195509293505050565b5f5f604083850312156156d0575f5ffd5b82356156db81614b6c565b915060208301356001600160401b038111156156f5575f5ffd5b613e6b858286016153a1565b634e487b7160e01b5f52603260045260245ffd5b5f8235603e19833603018112615729575f5ffd5b9190910192915050565b5f60208284031215615743575f5ffd5b61087d82614b80565b5f5f8335601e19843603018112615761575f5ffd5b8301803591506001600160401b0382111561577a575f5ffd5b6020019150600581901b3603821315611045575f5ffd5b5f602082840312156157a1575f5ffd5b813561ffff8116811461087d575f5ffd5b5f602082840312156157c2575f5ffd5b8151801515811461087d575f5ffd5b604081016109328284614cea565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190811115610932576109326157df565b8183526020830192505f815f5b84811015614d435763ffffffff61583283614b80565b168652602095860195919091019060010161581c565b6001600160a01b038581168252841660208201526060604082018190525f906108b3908301848661580f565b6001600160a01b038616815260c081016158916020830187614cea565b6001600160a01b039490941660608201526001600160401b0392909216608083015263ffffffff1660a09091015292915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f610b716020830184866158c5565b5f5f8335601e19843603018112615915575f5ffd5b8301803591506001600160401b0382111561592e575f5ffd5b602001915036819003821315611045575f5ffd5b6001600160a01b038781168252861660208201526080604082018190525f9061596e908301868861580f565b82810360608401526159818185876158c5565b9998505050505050505050565b6060810161599c8285614cea565b6001600160a01b039290921660409190910152919050565b805160208083015191908110156153b1575f1960209190910360031b1b16919050565b604081525f6159e960408301856151a9565b82810360208401526114e781856151a9565b5f60208284031215615a0b575f5ffd5b81516001600160401b03811115615a20575f5ffd5b8201601f81018413615a30575f5ffd5b8051615a3e614e2e82614def565b8082825260208201915060208360051b850101925086831115615a5f575f5ffd5b602084015b83811015615afc5780516001600160401b03811115615a81575f5ffd5b8501603f81018913615a91575f5ffd5b6020810151615aa2614e2e82614def565b808282526020820191506020808460051b8601010192508b831115615ac5575f5ffd5b6040840193505b82841015615ae7578351825260209384019390910190615acc565b86525050602093840193919091019050615a64565b509695505050505050565b5f60018201615b1857615b186157df565b5060010190565b81810381811115610932576109326157df565b6001600160401b038281168282160390811115610932576109326157df565b5f81600f0b60016001607f1b03198103615b6d57615b6d6157df565b5f0392915050565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610932576109326157df565b6001600160a01b038716815260e08101615bbf6020830188614cea565b60608201959095526001600160a01b039390931660808401526001600160401b0391821660a08401521660c09091015292915050565b5f60208284031215615c05575f5ffd5b5051919050565b6001600160a01b03881681525f60c08201615c2a602084018a614cea565b60c060608401528690528660e083015f5b88811015615c6b578235615c4e81614b6c565b6001600160a01b0316825260209283019290910190600101615c3b565b508381036080850152615c7e8188614ef7565b91505082810360a0840152615c948185876158c5565b9a9950505050505050505050565b5f81615cb057615cb06157df565b505f190190565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610932576109326157df565b5f60208284031215615cf4575f5ffd5b815161087d81614b6c565b8082018281125f831280158216821582161715615d1e57615d1e6157df565b505092915050565b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b80820180821115610932576109326157df565b5f82615d8f57634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212204822a3705860d0223c89242417e05d3a5345087df963e57606c2b5c3d238326364736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" - } - }, - "9": { - "address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", - "code": "0x735fc8d32690cc91d4c39d9d3abcbd16989f875707301460806040526004361061006b575f3560e01c8063017b73111461006f578063253946451461009057806365529675146100af5780638257f3d5146100ce578063ae8a4d98146100ed578063fe1aa59d1461010c575b5f5ffd5b81801561007a575f5ffd5b5061008e61008936600461080c565b61012b565b005b81801561009b575f5ffd5b5061008e6100aa36600461080c565b610155565b8180156100ba575f5ffd5b5061008e6100c9366004610860565b6101db565b8180156100d9575f5ffd5b5061008e6100e836600461080c565b610267565b8180156100f8575f5ffd5b5061008e61010736600461080c565b6102f8565b818015610117575f5ffd5b5061008e6101263660046108ae565b610328565b5f610138828401846109a7565b9050610150815f0151826020015183604001516103a5565b505050565b5f61016282840184610a68565b80516020820151604080840151905163a3499c7360e01b8152939450732279b7a0a67db372996a5fab50d91eaa73d2ebe69363a3499c73936101aa9390929091600401610b1b565b5f6040518083038186803b1580156101c0575f5ffd5b505af41580156101d2573d5f5f3e3d5ffd5b50505050505050565b5f6101e882840184610b4a565b90505f6102147f81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79610414565b82519091506001600160a01b0316610248576102438582846020015185604001516001600160801b031661046c565b610260565b6102608582845f0151856020015186604001516104c9565b5050505050565b5f61027482840184610b7b565b80517e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ab805492935091829060ff1916600183818111156102b5576102b5610bc9565b021790555081516040517f4016a1377b8961c4aa6f3a2d3de830a685ddbfe0f228ffc0208eb96304c4cf1a916102ea91610bdd565b60405180910390a150505050565b5f61030582840184610c03565b9050610322815f015182602001518360400151846060015161052e565b50505050565b5f61033582840184610cbd565b90505f61034186610414565b90505f825f01518360200151846040015160405160240161036493929190610d45565b60408051601f198184030181529190526020810180516001600160e01b031663c6b295c160e01b179052905061039b828783610679565b5050505050505050565b5f6103af84610705565b6040516340c10f1960e01b81526001600160a01b0385811660048301526001600160801b0385166024830152919250908216906340c10f19906044015f604051808303815f87803b158015610402575f5ffd5b505af115801561039b573d5f5f3e3d5ffd5b5f8181527e96e2f02350077f4ff1746770dbe5db3c04b7db2c8763c8fc21bf66b35e96ad60205260409020546001600160a01b0316806104675760405163d3227c9b60e01b815260040160405180910390fd5b919050565b6040516001600160a01b0383166024820152604481018290525f9060640160408051601f198184030181529190526020810180516001600160e01b03166305b1137b60e01b17905290506104c1848683610679565b505050505050565b6040516001600160a01b038085166024830152831660448201526001600160801b03821660648201525f9060840160408051601f198184030181529190526020810180516001600160e01b03166309733b7b60e21b17905290506101d2858783610679565b5f8481527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b0316156105a457604051633ea7ffd960e11b815260040160405180910390fd5b5f8585856040516105b4906107bb565b6105c093929190610d78565b604051809103905ff0801580156105d9573d5f5f3e3d5ffd5b50604080518082018252600180825260208083018c81525f8d815260048901835285812080546001600160a01b0319166001600160a01b038916908117909155808252898452908690208551815460ff19169015151781559151919093015592519081529293509189917f57f58171b8777633d03aff1e7408b96a3d910c93a7ce433a8cb7fb837dc306a6910160405180910390a2509695505050505050565b60605f5f856001600160a01b0316639bb66b2886866040518363ffffffff1660e01b81526004016106ab929190610db0565b5f604051808303815f875af11580156106c6573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106ed9190810190610ddb565b915091506106fb8282610796565b9695505050505050565b5f8181527f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c23260205260408120547f8d3b47662f045c362f825b520d7ddf7a0e5f6703a828606de6840b3652b8c22e906001600160a01b031661077a5760405163259ba1ad60e01b815260040160405180910390fd5b5f9283526004016020525060409020546001600160a01b031690565b606082156107a55750806107b5565b81511561006b5781518083602001fd5b92915050565b610c3580610e6883390190565b5f5f83601f8401126107d8575f5ffd5b5081356001600160401b038111156107ee575f5ffd5b602083019150836020828501011115610805575f5ffd5b9250929050565b5f5f6020838503121561081d575f5ffd5b82356001600160401b03811115610832575f5ffd5b61083e858286016107c8565b90969095509350505050565b80356001600160a01b0381168114610467575f5ffd5b5f5f5f60408486031215610872575f5ffd5b61087b8461084a565b925060208401356001600160401b03811115610895575f5ffd5b6108a1868287016107c8565b9497909650939450505050565b5f5f5f5f606085870312156108c1575f5ffd5b843593506108d16020860161084a565b925060408501356001600160401b038111156108eb575f5ffd5b6108f7878288016107c8565b95989497509550505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561093957610939610903565b60405290565b604051608081016001600160401b038111828210171561093957610939610903565b604051601f8201601f191681016001600160401b038111828210171561098957610989610903565b604052919050565b80356001600160801b0381168114610467575f5ffd5b5f60608284031280156109b8575f5ffd5b506109c1610917565b823581526109d16020840161084a565b60208201526109e260408401610991565b60408201529392505050565b5f6001600160401b03821115610a0657610a06610903565b50601f01601f191660200190565b5f82601f830112610a23575f5ffd5b8135602083015f610a3b610a36846109ee565b610961565b9050828152858383011115610a4e575f5ffd5b828260208301375f92810160200192909252509392505050565b5f60208284031215610a78575f5ffd5b81356001600160401b03811115610a8d575f5ffd5b820160608185031215610a9e575f5ffd5b610aa6610917565b610aaf8261084a565b81526020828101359082015260408201356001600160401b03811115610ad3575f5ffd5b610adf86828501610a14565b604083015250949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60018060a01b0384168152826020820152606060408201525f610b416060830184610aed565b95945050505050565b5f6060828403128015610b5b575f5ffd5b50610b64610917565b610b6d8361084a565b81526109d16020840161084a565b5f6020828403128015610b8c575f5ffd5b50604051602081016001600160401b0381118282101715610baf57610baf610903565b604052823560028110610bc0575f5ffd5b81529392505050565b634e487b7160e01b5f52602160045260245ffd5b6020810160028310610bfd57634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215610c13575f5ffd5b81356001600160401b03811115610c28575f5ffd5b820160808185031215610c39575f5ffd5b610c4161093f565b8135815260208201356001600160401b03811115610c5d575f5ffd5b610c6986828501610a14565b60208301525060408201356001600160401b03811115610c87575f5ffd5b610c9386828501610a14565b6040830152506060820135915060ff82168214610cae575f5ffd5b60608101919091529392505050565b5f60208284031215610ccd575f5ffd5b81356001600160401b03811115610ce2575f5ffd5b820160608185031215610cf3575f5ffd5b610cfb610917565b610d048261084a565b815260208201356001600160401b03811115610d1e575f5ffd5b610d2a86828501610a14565b60208301525060408201356040820152809250505092915050565b6001600160a01b03841681526060602082018190525f90610d6890830185610aed565b9050826040830152949350505050565b606081525f610d8a6060830186610aed565b8281036020840152610d9c8186610aed565b91505060ff83166040830152949350505050565b6001600160a01b03831681526040602082018190525f90610dd390830184610aed565b949350505050565b5f5f60408385031215610dec575f5ffd5b82518015158114610dfb575f5ffd5b60208401519092506001600160401b03811115610e16575f5ffd5b8301601f81018513610e26575f5ffd5b8051610e34610a36826109ee565b818152866020838501011115610e48575f5ffd5b8160208401602083015e5f60208383010152809350505050925092905056fe60c060405234801561000f575f5ffd5b50604051610c35380380610c3583398101604081905261002e916100f5565b5f61003984826101f6565b50600161004683826101f6565b5060ff1660a0525050336080526102b0565b634e487b7160e01b5f52604160045260245ffd5b5f82601f83011261007b575f5ffd5b81516001600160401b0381111561009457610094610058565b604051601f8201601f19908116603f011681016001600160401b03811182821017156100c2576100c2610058565b6040528181528382016020018510156100d9575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f60608486031215610107575f5ffd5b83516001600160401b0381111561011c575f5ffd5b6101288682870161006c565b602086015190945090506001600160401b03811115610145575f5ffd5b6101518682870161006c565b925050604084015160ff81168114610167575f5ffd5b809150509250925092565b600181811c9082168061018657607f821691505b6020821081036101a457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156101f157805f5260205f20601f840160051c810160208510156101cf5750805b601f840160051c820191505b818110156101ee575f81556001016101db565b50505b505050565b81516001600160401b0381111561020f5761020f610058565b6102238161021d8454610172565b846101aa565b6020601f821160018114610255575f831561023e5750848201515b5f19600385901b1c1916600184901b1784556101ee565b5f84815260208120601f198516915b828110156102845787850151825560209485019460019092019101610264565b50848210156102a157868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60805160a0516109566102df5f395f61019e01525f818161013a015281816104f301526105c201526109565ff3fe608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c806340c10f19116100935780639dc29fac116100635780639dc29fac14610247578063a9059cbb1461025a578063d505accf1461026d578063dd62ed3e14610280575f5ffd5b806340c10f19146101da57806370a08231146101ef5780637ecebe001461021757806395d89b411461023f575f5ffd5b806318160ddd116100ce57806318160ddd1461017457806323b872dd14610186578063313ce567146101995780633644e515146101d2575f5ffd5b806306fdde03146100f4578063095ea7b314610112578063116191b614610135575b5f5ffd5b6100fc6102b8565b6040516101099190610749565b60405180910390f35b610125610120366004610799565b610343565b6040519015158152602001610109565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610109565b6005545b604051908152602001610109565b6101256101943660046107c1565b6103d5565b6101c07f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610109565b61017861046f565b6101ed6101e8366004610799565b6104e8565b005b6101786101fd3660046107fb565b6001600160a01b03165f9081526002602052604090205490565b6101786102253660046107fb565b6001600160a01b03165f9081526004602052604090205490565b6100fc6105aa565b6101ed610255366004610799565b6105b7565b610125610268366004610799565b61064d565b6101ed61027b366004610814565b61069d565b61017861028e366004610881565b6001600160a01b039182165f90815260036020908152604080832093909416825291909152205490565b5f80546102c4906108b2565b80601f01602080910402602001604051908101604052809291908181526020018280546102f0906108b2565b801561033b5780601f106103125761010080835404028352916020019161033b565b820191905f5260205f20905b81548152906001019060200180831161031e57829003601f168201915b505050505081565b6040516338412ce560e01b8152600260048201526001600160a01b0383166024820152604481018290525f9073a513e6e4b8f2a923d98304ec87f64353c4d5c853906338412ce5906064015b602060405180830381865af41580156103aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ce91906108ea565b9392505050565b6040516301b8d43b60e41b8152600260048201526001600160a01b03808516602483015283166044820152606481018290525f9073a513e6e4b8f2a923d98304ec87f64353c4d5c85390631b8d43b090608401602060405180830381865af4158015610443573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061046791906108ea565b949350505050565b6040516312af95d360e31b81525f600482018190529073a513e6e4b8f2a923d98304ec87f64353c4d5c8539063957cae9890602401602060405180830381865af41580156104bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e39190610909565b905090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610530576040516282b42960e81b815260040160405180910390fd5b60405163480ff06560e01b8152600260048201526001600160a01b03831660248201526044810182905273a513e6e4b8f2a923d98304ec87f64353c4d5c8539063480ff065906064015b5f6040518083038186803b158015610590575f5ffd5b505af41580156105a2573d5f5f3e3d5ffd5b505050505050565b600180546102c4906108b2565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105ff576040516282b42960e81b815260040160405180910390fd5b60405163c7f6238760e01b8152600260048201526001600160a01b03831660248201526044810182905273a513e6e4b8f2a923d98304ec87f64353c4d5c8539063c7f623879060640161057a565b60405163379bc60360e11b8152600260048201526001600160a01b0383166024820152604481018290525f9073a513e6e4b8f2a923d98304ec87f64353c4d5c85390636f378c069060640161038f565b604051630334f36960e31b8152600260048201525f60248201526001600160a01b038089166044830152871660648201526084810186905260a4810185905260ff841660c482015260e48101839052610104810182905273a513e6e4b8f2a923d98304ec87f64353c4d5c853906319a79b4890610124015f6040518083038186803b15801561072a575f5ffd5b505af415801561073c573d5f5f3e3d5ffd5b5050505050505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610794575f5ffd5b919050565b5f5f604083850312156107aa575f5ffd5b6107b38361077e565b946020939093013593505050565b5f5f5f606084860312156107d3575f5ffd5b6107dc8461077e565b92506107ea6020850161077e565b929592945050506040919091013590565b5f6020828403121561080b575f5ffd5b6103ce8261077e565b5f5f5f5f5f5f5f60e0888a03121561082a575f5ffd5b6108338861077e565b96506108416020890161077e565b95506040880135945060608801359350608088013560ff81168114610864575f5ffd5b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215610892575f5ffd5b61089b8361077e565b91506108a96020840161077e565b90509250929050565b600181811c908216806108c657607f821691505b6020821081036108e457634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156108fa575f5ffd5b815180151581146103ce575f5ffd5b5f60208284031215610919575f5ffd5b505191905056fea2646970667358221220e1f5b5d05dc7259c2004ce8b2365485a31341d166e578c6bed74cf416d43d0b864736f6c634300081c0033a2646970667358221220bf51267d76cff7222c17d610dde7751957cfe3a183e053d0666ff0994eb90d2f64736f6c634300081c0033000000000000000000", - "storage": {} - }, - "43": { - "address": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", - "code": "0x73cf7ed3acca5a467e9e704c703e8d87f634fb0fc93014608060405260043610610034575f3560e01c8063d3b08db814610038575b5f5ffd5b61004b610046366004610370565b610061565b6040516100589190610465565b60405180910390f35b805180516060915f83815b83518163ffffffff1610156101065781848263ffffffff16815181106100945761009461049a565b60200260200101516040516020016100c4919060609190911b6bffffffffffffffffffffffff1916815260140190565b60408051601f19818403018152908290526100e292916020016104c5565b604051602081830303815290604052915080806100fe906104f5565b91505061006c565b50630e02a00760e31b5f8061011a876101ac565b8465ff000000ff00600888811b91821664ff000000ff918a901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b60405160200161019296959493929190610519565b604051602081830303815290604052945050505050919050565b6060603f8263ffffffff16116101e957604051603f60fa1b60fa84901b1660208201526021015b6040516020818303038152906040529050919050565b613fff8263ffffffff1611610248576102256102116403fffffffc600285901b166001610572565b600881811b62ffff001691901c60ff161790565b6040516020016101d3919060f09190911b6001600160f01b031916815260020190565b633fffffff8263ffffffff16116102ba5761029760028363ffffffff16901b60026102739190610572565b600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1790565b6040516020016101d3919060e09190911b6001600160e01b031916815260040190565b604051600360f81b60208201526001600160e01b0319600884811c62ff00ff1663ff00ff009186901b9190911617601081811c91901b1760e01b1660218201526025016101d3565b634e487b7160e01b5f52604160045260245ffd5b6040516020810167ffffffffffffffff8111828210171561033957610339610302565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561036857610368610302565b604052919050565b5f60208284031215610380575f5ffd5b813567ffffffffffffffff811115610396575f5ffd5b8201602081850312156103a7575f5ffd5b6103af610316565b813567ffffffffffffffff8111156103c5575f5ffd5b80830192505084601f8301126103d9575f5ffd5b813567ffffffffffffffff8111156103f3576103f3610302565b8060051b6104036020820161033f565b9182526020818501810192908101908884111561041e575f5ffd5b6020860195505b8386101561045757853592506001600160a01b0383168314610445575f5ffd5b82825260209586019590910190610425565b845250919695505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f6104d96104d383866104ae565b846104ae565b949350505050565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff8103610510576105106104e1565b60010192915050565b6001600160e01b0319871681526001600160f81b03198681166004830152851660058201525f61055561054f60068401876104ae565b856104ae565b6001600160c01b0319939093168352505060080195945050505050565b63ffffffff818116838216019081111561058e5761058e6104e1565b9291505056fea2646970667358221220ec754a565932b22e059c17b06dbd28b7721de4df0054b69f4983510c827d2c9364736f6c634300081c0033000000000000000000000000000000000000", - "storage": {} - }, - "34": { - "address": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000009635f643e140090a9a8dcd712ed6285858cebef", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x00000000000000000000000000000000000000000000000000000000000000cb": "0x000003e80000000000001c2090f79bf6eb2c4f870365e785982e1f101e93b906", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65" - } - }, - "5": { - "address": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", - "code": "0x738a791620dd6260079bf849dc5567adc3f2fdc3183014608060405260043610610090575f3560e01c8063ab55562e11610063578063ab55562e146100fd578063af18d14214610105578063c82b5f451461010d578063ded905d514610115575f5ffd5b80632db726161461009457806379d0e91c146100bc5780637cb1a954146100e05780639ce504ff146100f6575b5f5ffd5b6100a76100a23660046109da565b61011c565b60405190151581526020015b60405180910390f35b6100c7600160f81b81565b6040516001600160f81b031990911681526020016100b3565b6100e8600581565b6040519081526020016100b3565b6100c75f81565b6100e8600681565b6100e8600481565b6100e8600881565b6100e85f81565b5f6101318461012b8580610a64565b84610278565b61013c57505f61026f565b6101496020840184610a82565b6020013583806020019061015d9190610a82565b351061016a57505f61026f565b5f61017e866101798680610a64565b610419565b90505f6101c7826101926020880188610a82565b356101a06020890189610a82565b602001358880602001906101b49190610a82565b6101c2906040810190610a96565b610434565b90505f6101e56101df36889003880160408901610b1d565b836104da565b90506001600160a01b03891663a401662b826102056101008a018a610a96565b8a61012001356040518563ffffffff1660e01b815260040161022a9493929190610bbc565b602060405180830381865afa158015610245573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102699190610c00565b93505050505b95945050505050565b5f5f82610285575f61028b565b600160f81b5b90505f5b61029c6080860186610a96565b905081101561040c575f6102b36080870187610a96565b838181106102c3576102c3610c1b565b90506020028101906102d59190610a82565b3514801561032157506102eb6080860186610a96565b828181106102fb576102fb610c1b565b905060200281019061030d9190610a82565b61031b906040810190610c2f565b90506021145b801561039657506001600160f81b031982166103406080870187610a96565b8381811061035057610350610c1b565b90506020028101906103629190610a82565b610370906040810190610c2f565b5f81811061038057610380610c1b565b9050013560f81c60f81b6001600160f81b031916145b80156103f457506103aa6080860186610a96565b828181106103ba576103ba610c1b565b90506020028101906103cc9190610a82565b6103da906040810190610c2f565b6103e8916001908290610c72565b6103f191610c99565b86145b1561040457600192505050610412565b60010161028f565b505f9150505b9392505050565b5f610424838361062c565b8051906020012090505b92915050565b5f85815b838110156104cf57866001166001148061045457508587600101145b1561048b5761048485858381811061046e5761046e610c1b565b90506020020135835f9182526020526040902090565b91506104b9565b6104b6828686848181106104a1576104a1610c1b565b905060200201355f9182526020526040902090565b91505b600196871c965f19909601861c86019501610438565b509695505050505050565b81515f90819060f81b6105128560200151600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1760e01b90565b856040015161058887606001515f65ff000000ff00600883811b91821664ff000000ff9185901c91821617601090811b67ff000000ff0000009390931666ff000000ff00009290921691909117901c17602081811b6bffffffffffffffff000000001691901c63ffffffff161760c01b92915050565b6080880151600881811b63ff00ff001662ff00ff9290911c9190911617601081811b91901c1760e01b60a08901516040516001600160f81b031990961660208701526001600160e01b0319948516602187015260258601939093526001600160c01b0319909116604585015291909116604d83015260518201526071810184905260910160408051808303601f190181529190528051602090910120949350505050565b60605f823561063e60208501356106b8565b6040850135606086013561065d6106586080890189610a96565b6106e8565b604051602001610671959493929190610ccd565b60405160208183030381529060405290508361068d82516106b8565b826040516020016106a093929190610d00565b60405160208183030381529060405291505092915050565b606063ffffffff8211156106df57604051637404cccd60e11b815260040160405180910390fd5b61042e82610778565b60408051602081019091525f808252606091905b8381101561075c578161073186868481811061071a5761071a610c1b565b905060200281019061072c9190610a82565b6108d3565b604051602001610742929190610d24565b60408051601f1981840301815291905291506001016106fc565b50610766836106b8565b816040516020016106a0929190610d24565b6060603f8263ffffffff16116107b557604051603f60fa1b60fa84901b1660208201526021015b6040516020818303038152906040529050919050565b613fff8263ffffffff1611610814576107f16107dd6403fffffffc600285901b166001610d3a565b600881811b62ffff001691901c60ff161790565b60405160200161079f919060f09190911b6001600160f01b031916815260020190565b633fffffff8263ffffffff16116108865761086360028363ffffffff16901b600261083f9190610d3a565b600881811c62ff00ff1663ff00ff009290911b9190911617601081811c91901b1790565b60405160200161079f919060e09190911b6001600160e01b031916815260040190565b604051600360f81b60208201526001600160e01b0319600884811c62ff00ff1663ff00ff009186901b9190911617601081811c91901b1760e01b16602182015260250161079f565b919050565b60608135600614806108e6575081356004145b806108f2575081356005145b1561094457813560f81b61090c6040840160208501610d62565b61092361091c6040860186610c2f565b90506106b8565b6109306040860186610c2f565b60405160200161079f959493929190610d7b565b813561097b575f61095b61091c6040850185610c2f565b6109686040850185610c2f565b60405160200161079f9493929190610dbb565b60071982350161099a57604051600160fb1b602082015260210161079f565b604051635422005560e11b815260040160405180910390fd5b80356001600160e01b0319811681146108ce575f5ffd5b80151581146109d7575f5ffd5b50565b5f5f5f5f5f60a086880312156109ee575f5ffd5b85356001600160a01b0381168114610a04575f5ffd5b9450610a12602087016109b3565b935060408601359250606086013567ffffffffffffffff811115610a34575f5ffd5b86016101408189031215610a46575f5ffd5b91506080860135610a56816109ca565b809150509295509295909350565b5f8235609e19833603018112610a78575f5ffd5b9190910192915050565b5f8235605e19833603018112610a78575f5ffd5b5f5f8335601e19843603018112610aab575f5ffd5b83018035915067ffffffffffffffff821115610ac5575f5ffd5b6020019150600581901b3603821315610adc575f5ffd5b9250929050565b803560ff811681146108ce575f5ffd5b803563ffffffff811681146108ce575f5ffd5b803567ffffffffffffffff811681146108ce575f5ffd5b5f60c0828403128015610b2e575f5ffd5b5060405160c0810167ffffffffffffffff81118282101715610b5e57634e487b7160e01b5f52604160045260245ffd5b604052610b6a83610ae3565b8152610b7860208401610af3565b602082015260408381013590820152610b9360608401610b06565b6060820152610ba460808401610af3565b608082015260a0928301359281019290925250919050565b84815260606020820181905281018390525f6001600160fb1b03841115610be1575f5ffd5b8360051b80866080850137604083019390935250016080019392505050565b5f60208284031215610c10575f5ffd5b8151610412816109ca565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e19843603018112610c44575f5ffd5b83018035915067ffffffffffffffff821115610c5e575f5ffd5b602001915036819003821315610adc575f5ffd5b5f5f85851115610c80575f5ffd5b83861115610c8c575f5ffd5b5050820193919092039150565b8035602083101561042e575f19602084900360031b1b1692915050565b5f81518060208401855e5f93019283525090919050565b8581525f610cde6020830187610cb6565b858152846020820152610cf46040820185610cb6565b98975050505050505050565b6001600160e01b0319841681525f61026f610d1e6004840186610cb6565b84610cb6565b5f610d32610d1e8386610cb6565b949350505050565b63ffffffff818116838216019081111561042e57634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610d72575f5ffd5b610412826109b3565b6001600160f81b0319861681526001600160e01b0319851660018201525f610da66005830186610cb6565b838582375f9301928352509095945050505050565b6001600160f81b0319851681525f610dd66001830186610cb6565b838582375f9301928352509094935050505056fea2646970667358221220367283a645a6f2ff4567a6b7f3c48a7618ad09eda48237419b569370b356fa4d64736f6c634300081c0033000000", - "storage": {} - }, - "31": { - "address": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1", - "code": "0x60806040523661001357610011610017565b005b6100115b61001f610168565b6001600160a01b0316330361015e5760606001600160e01b03195f35166364d3180d60e11b81016100595761005261019a565b9150610156565b63587086bd60e11b6001600160e01b0319821601610079576100526101ed565b63070d7c6960e41b6001600160e01b031982160161009957610052610231565b621eb96f60e61b6001600160e01b03198216016100b857610052610261565b63a39f25e560e01b6001600160e01b03198216016100d8576100526102a0565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101666102b3565b565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a46102c3565b5f6101b23660048184610668565b8101906101bf91906106aa565b90506101da8160405180602001604052805f8152505f6102cd565b505060408051602081019091525f815290565b60605f806101fe3660048184610668565b81019061020b91906106d7565b9150915061021b828260016102cd565b60405180602001604052805f8152509250505090565b606061023b6102c3565b5f6102493660048184610668565b81019061025691906106aa565b90506101da816102f8565b606061026b6102c3565b5f610274610168565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102aa6102c3565b5f61027461034f565b6101666102be61034f565b61035d565b3415610166575f5ffd5b6102d68361037b565b5f825111806102e25750805b156102f3576102f183836103ba565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610321610168565b604080516001600160a01b03928316815291841660208301520160405180910390a161034c816103e6565b50565b5f61035861048f565b905090565b365f5f375f5f365f845af43d5f5f3e808015610377573d5ff35b3d5ffd5b610384816104b6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606103df83836040518060600160405280602781526020016107e76027913961054a565b9392505050565b6001600160a01b03811661044b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014d565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018b565b6001600160a01b0381163b6105235760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014d565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61046e565b60605f5f856001600160a01b031685604051610566919061079b565b5f60405180830381855af49150503d805f811461059e576040519150601f19603f3d011682016040523d82523d5f602084013e6105a3565b606091505b50915091506105b4868383876105be565b9695505050505050565b6060831561062c5782515f03610625576001600160a01b0385163b6106255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014d565b5081610636565b610636838361063e565b949350505050565b81511561064e5781518083602001fd5b8060405162461bcd60e51b815260040161014d91906107b1565b5f5f85851115610676575f5ffd5b83861115610682575f5ffd5b5050820193919092039150565b80356001600160a01b03811681146106a5575f5ffd5b919050565b5f602082840312156106ba575f5ffd5b6103df8261068f565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156106e8575f5ffd5b6106f18361068f565b9150602083013567ffffffffffffffff81111561070c575f5ffd5b8301601f8101851361071c575f5ffd5b803567ffffffffffffffff811115610736576107366106c3565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610765576107656106c3565b60405281815282820160200187101561077c575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220861fd99925c9a795ce816251fa5b602392756b97b9314cad5a76d14fa0bea07364736f6c634300081c003300", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000610178da211fef7d417bc0e6fed39f05609ad788", - "0x0000000000000000000000000000000000000000000000000000000000000033": "0x00000000000000000000000015d34aaf54267db7d7c367839aaf71a00a2c6a65", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000007a2088a1bfc9d81c55368ae168c2c02570cb814f" + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7", + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b" } }, "3": { - "address": "0x09635F643e140090A9A8Dcd712eD6285858ceBef", - "code": "0x608060405234801561000f575f5ffd5b50600436106103b3575f3560e01c8063886f1195116101f5578063de02e50311610114578063f6efbb59116100a9578063fabc1cbc11610079578063fabc1cbc14610a33578063fbf1e2c114610a46578063fce36c7d14610a59578063ff9f6cce14610a6c575f5ffd5b8063f6efbb59146109e7578063f74e8eac146109fa578063f8cd844814610a0d578063f96abf2e14610a20575f5ffd5b8063ed71e6a2116100e4578063ed71e6a214610967578063f22cef8514610994578063f2f07ab4146109a7578063f2fde38b146109d4575f5ffd5b8063de02e50314610907578063e063f81f1461091a578063e810ce211461092d578063ea4d3c9b14610940575f5ffd5b8063a50a1d9c1161018a578063bf21a8aa1161015a578063bf21a8aa14610879578063c46db606146108a0578063ca8aa7c7146108cd578063dcbb03b3146108f4575f5ffd5b8063a50a1d9c14610807578063aebd8bae1461081a578063b3dbb0e014610847578063bb7e451f1461085a575f5ffd5b80639cb9a5fa116101c55780639cb9a5fa146107a75780639d45c281146107ba5780639de4b35f146107e1578063a0169ddd146107f4575f5ffd5b8063886f11951461074c5780638da5cb5b146107735780639104c319146107845780639be3d4e41461079f575f5ffd5b80634596021c116102e15780635c975abb11610276578063715018a611610246578063715018a6146106ff5780637b8f8b0514610707578063863cb9a91461070f578063865c695314610722575f5ffd5b80635c975abb146106a25780635e9d8348146106aa57806363f6a798146106bd5780636d21117e146106d2575f5ffd5b806354fd4d50116102b157806354fd4d501461064f57806358baaa3e14610664578063595c6a67146106775780635ac86ab71461067f575f5ffd5b80634596021c146105d85780634657e26a146105eb5780634b943960146106125780634d18cc3514610638575f5ffd5b8063149bc8721161035757806339b70e381161032757806339b70e38146105745780633a8c07861461059b5780633ccc861d146105b25780633efe1db6146105c5575f5ffd5b8063149bc872146104d95780632b9f64a4146104fa57806336af41fa1461053a57806337838ed01461054d575f5ffd5b80630e9a53cf116103925780630e9a53cf1461043f5780630eb383451461048c578063131433b41461049f578063136439dd146104c6575f5ffd5b806218572c146103b757806304a0c502146103ee5780630ca298991461042a575b5f5ffd5b6103d96103c5366004613a33565b60d16020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6104157f0000000000000000000000000000000000000000000000000000000000278d0081565b60405163ffffffff90911681526020016103e5565b61043d610438366004613aab565b610a7f565b005b610447610d25565b6040516103e591905f6080820190508251825263ffffffff602084015116602083015263ffffffff604084015116604083015260608301511515606083015292915050565b61043d61049a366004613b07565b610e25565b6104157f0000000000000000000000000000000000000000000000000000000065fb788081565b61043d6104d4366004613b3e565b610ea5565b6104ec6104e7366004613b55565b610edf565b6040519081526020016103e5565b610522610508366004613a33565b60cc6020525f90815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103e5565b61043d610548366004613b6f565b610f54565b6104157f000000000000000000000000000000000000000000000000000000000076a70081565b6105227f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb60750881565b60cb5461041590600160a01b900463ffffffff1681565b61043d6105c0366004613bbe565b6110c5565b61043d6105d3366004613c14565b6110ec565b61043d6105e6366004613c3e565b6112c2565b6105227f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c81565b610625610620366004613a33565b611325565b60405161ffff90911681526020016103e5565b60cb5461041590600160c01b900463ffffffff1681565b610657611380565b6040516103e59190613c90565b61043d610672366004613cc5565b6113b0565b61043d6113c4565b6103d961068d366004613cde565b606654600160ff9092169190911b9081161490565b6066546104ec565b6103d96106b8366004613cfe565b6113d8565b60cb5461062590600160e01b900461ffff1681565b6103d96106e0366004613d2f565b60cf60209081525f928352604080842090915290825290205460ff1681565b61043d611463565b60ca546104ec565b61043d61071d366004613a33565b611474565b6104ec610730366004613d59565b60cd60209081525f928352604080842090915290825290205481565b6105227f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e81565b6033546001600160a01b0316610522565b61052273beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b610447611485565b61043d6107b5366004613d85565b611521565b6104157f000000000000000000000000000000000000000000000000000000000001518081565b6106256107ef366004613dbc565b61169c565b61043d610802366004613a33565b61171f565b61043d610815366004613df8565b61172a565b6103d9610828366004613d2f565b60d260209081525f928352604080842090915290825290205460ff1681565b61043d610855366004613e11565b61173b565b6104ec610868366004613a33565b60ce6020525f908152604090205481565b6104157f00000000000000000000000000000000000000000000000000000000005c490081565b6103d96108ae366004613d2f565b60d060209081525f928352604080842090915290825290205460ff1681565b6105227f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed81565b61043d610902366004613e3b565b611866565b610447610915366004613b3e565b6119b3565b610625610928366004613d59565b611a43565b61041561093b366004613b3e565b611aa8565b6105227f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd8281565b6103d9610975366004613d2f565b60d360209081525f928352604080842090915290825290205460ff1681565b61043d6109a2366004613d59565b611b29565b6103d96109b5366004613d2f565b60d760209081525f928352604080842090915290825290205460ff1681565b61043d6109e2366004613a33565b611c93565b61043d6109f5366004613e7f565b611d0e565b61043d610a08366004613edd565b611e43565b6104ec610a1b366004613b55565b61200a565b61043d610a2e366004613cc5565b61201a565b61043d610a41366004613b3e565b61214b565b60cb54610522906001600160a01b031681565b61043d610a67366004613b6f565b6121b8565b61043d610a7a366004613b6f565b6122e9565b6009610a8a8161244a565b610a976020850185613a33565b610aa081612475565b610abd5760405163932d94f760e01b815260040160405180910390fd5b610ac561251f565b6040516304c1b8eb60e31b81526001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063260dc75890610b11908890600401613f48565b602060405180830381865afa158015610b2c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b509190613f56565b610b6d57604051631fb1705560e21b815260040160405180910390fd5b5f5b83811015610d135736858583818110610b8a57610b8a613f71565b9050602002810190610b9c9190613f85565b90505f60ce81610baf60208b018b613a33565b6001600160a01b031681526020808201929092526040015f90812054925090610bda908a018a613a33565b8284604051602001610bee939291906141ad565b6040516020818303038152906040528051906020012090505f610c1084612578565b9050600160d75f610c2460208e018e613a33565b6001600160a01b0316815260208082019290925260409081015f9081208682529092529020805460ff1916911515919091179055610c638360016141f0565b60ce5f610c7360208e018e613a33565b6001600160a01b03166001600160a01b031681526020019081526020015f208190555081336001600160a01b03167ffff0759ccb371dfb5691798724e70b4fa61cb3bfe730a33ac19fb86a48efc7568c8688604051610cd493929190614203565b60405180910390a3610d03333083610cf26040890160208a01613a33565b6001600160a01b0316929190612763565b505060019092019150610b6f9050565b50610d1e6001609755565b5050505050565b604080516080810182525f80825260208201819052918101829052606081019190915260ca545b8015610dfd575f60ca610d60600184614228565b81548110610d7057610d70613f71565b5f91825260209182902060408051608081018252600293909302909101805483526001015463ffffffff80821694840194909452600160201b810490931690820152600160401b90910460ff161580156060830181905291925090610ddf5750806040015163ffffffff164210155b15610dea5792915050565b5080610df58161423b565b915050610d4c565b5050604080516080810182525f80825260208201819052918101829052606081019190915290565b610e2d6127ce565b6001600160a01b0382165f81815260d1602052604080822054905160ff9091169284151592841515927f4de6293e668df1398422e1def12118052c1539a03cbfedc145895d48d7685f1c9190a4506001600160a01b03919091165f90815260d160205260409020805460ff1916911515919091179055565b610ead612828565b6066548181168114610ed25760405163c61dca5d60e01b815260040160405180910390fd5b610edb826128cb565b5050565b5f80610eee6020840184613a33565b8360200135604051602001610f379392919060f89390931b6001600160f81b031916835260609190911b6bffffffffffffffffffffffff19166001830152601582015260350190565b604051602081830303815290604052805190602001209050919050565b6001610f5f8161244a565b335f90815260d1602052604090205460ff16610f8e57604051635c427cd960e01b815260040160405180910390fd5b610f9661251f565b5f5b828110156110b55736848483818110610fb357610fb3613f71565b9050602002810190610fc59190614250565b335f81815260ce60209081526040808320549051949550939192610fef92909185918791016142e2565b60405160208183030381529060405280519060200120905061101083612908565b335f90815260d0602090815260408083208484529091529020805460ff191660019081179091556110429083906141f0565b335f81815260ce602052604090819020929092559051829184917f51088b8c89628df3a8174002c2a034d0152fce6af8415d651b2a4734bf27048290611089908890614308565b60405180910390a46110aa333060408601803590610cf29060208901613a33565b505050600101610f98565b506110c06001609755565b505050565b60026110d08161244a565b6110d861251f565b6110e283836129f3565b6110c06001609755565b60036110f78161244a565b60cb546001600160a01b0316331461112257604051635c427cd960e01b815260040160405180910390fd5b60cb5463ffffffff600160c01b90910481169083161161115557604051631ca7e50b60e21b815260040160405180910390fd5b428263ffffffff161061117b576040516306957c9160e11b815260040160405180910390fd5b60ca5460cb545f9061119a90600160a01b900463ffffffff164261431a565b6040805160808101825287815263ffffffff87811660208084018281528684168587018181525f6060880181815260ca8054600181018255925297517f42d72674974f694b5f5159593243114d38a5c39c89d6b62fee061ff523240ee160029092029182015592517f42d72674974f694b5f5159593243114d38a5c39c89d6b62fee061ff523240ee290930180549151975193871667ffffffffffffffff1990921691909117600160201b978716979097029690961760ff60401b1916600160401b921515929092029190911790945560cb805463ffffffff60c01b1916600160c01b840217905593519283529394508892908616917fecd866c3c158fa00bf34d803d5f6023000b57080bcb48af004c2b4b46b3afd08910160405180910390a45050505050565b60026112cd8161244a565b6112d561251f565b5f5b838110156113145761130c8585838181106112f4576112f4613f71565b90506020028101906113069190614336565b846129f3565b6001016112d7565b5061131f6001609755565b50505050565b6001600160a01b0381165f90815260d5602090815260408083208151606081018352905461ffff80821683526201000082041693820193909352600160201b90920463ffffffff169082015261137a90612c7b565b92915050565b60606113ab7f76312e302e300000000000000000000000000000000000000000000000000006612ceb565b905090565b6113b86127ce565b6113c181612d28565b50565b6113cc612828565b6113d65f196128cb565b565b5f61145b8260ca6113ec6020830183613cc5565b63ffffffff168154811061140257611402613f71565b5f91825260209182902060408051608081018252600293909302909101805483526001015463ffffffff80821694840194909452600160201b810490931690820152600160401b90910460ff1615156060820152612d99565b506001919050565b61146b6127ce565b6113d65f612f3c565b61147c6127ce565b6113c181612f8d565b604080516080810182525f80825260208201819052918101829052606081019190915260ca80546114b890600190614228565b815481106114c8576114c8613f71565b5f91825260209182902060408051608081018252600293909302909101805483526001015463ffffffff80821694840194909452600160201b810490931690820152600160401b90910460ff1615156060820152919050565b600561152c8161244a565b8361153681612475565b6115535760405163932d94f760e01b815260040160405180910390fd5b61155b61251f565b5f5b83811015610d13573685858381811061157857611578613f71565b905060200281019061158a9190613f85565b6001600160a01b0388165f90815260ce60209081526040808320549051939450926115bb918b9185918791016141ad565b6040516020818303038152906040528051906020012090505f6115dd84612578565b6001600160a01b038b165f90815260d3602090815260408083208684529091529020805460ff1916600190811790915590915061161b9084906141f0565b6001600160a01b038b165f81815260ce60205260409081902092909255905183919033907ffc8888bffd711da60bc5092b33f677d81896fe80ecc677b84cfab8184462b6e09061166e9088908a9061434a565b60405180910390a461168c333083610cf26040890160208a01613a33565b50506001909201915061155d9050565b6001600160a01b0382165f90815260d66020526040812061171890826116cf6116ca36879003870187614362565b612fe8565b815260208082019290925260409081015f208151606081018352905461ffff80821683526201000082041693820193909352600160201b90920463ffffffff1690820152612c7b565b9392505050565b33610edb818361304b565b6117326127ce565b6113c1816130ae565b60076117468161244a565b8261175081612475565b61176d5760405163932d94f760e01b815260040160405180910390fd5b60cb545f9061178990600160a01b900463ffffffff164261431a565b6001600160a01b0386165f90815260d5602090815260408083208151606081018352905461ffff80821683526201000082041693820193909352600160201b90920463ffffffff1690820152919250906117e290612c7b565b6001600160a01b0387165f90815260d560205260409020909150611807908684613119565b6040805163ffffffff8416815261ffff838116602083015287168183015290516001600160a01b0388169133917fd1e028bd664486a46ad26040e999cd2d22e1e9a094ee6afe19fcf64678f16f749181900360600190a3505050505050565b60066118718161244a565b8361187b81612475565b6118985760405163932d94f760e01b815260040160405180910390fd5b60cb545f906118b490600160a01b900463ffffffff164261431a565b6001600160a01b038781165f90815260d460209081526040808320938a1683529281528282208351606081018552905461ffff80821683526201000082041692820192909252600160201b90910463ffffffff169281019290925291925061191b90612c7b565b6001600160a01b038089165f90815260d460209081526040808320938b1683529290522090915061194d908684613119565b6040805163ffffffff8416815261ffff838116602083015287168183015290516001600160a01b0388811692908a169133917f48e198b6ae357e529204ee53a8e514c470ff77d9cc8e4f7207f8b5d490ae6934919081900360600190a450505050505050565b604080516080810182525f80825260208201819052918101829052606081019190915260ca82815481106119e9576119e9613f71565b5f91825260209182902060408051608081018252600293909302909101805483526001015463ffffffff80821694840194909452600160201b810490931690820152600160401b90910460ff161515606082015292915050565b6001600160a01b038281165f90815260d46020908152604080832093851683529281528282208351606081018552905461ffff80821683526201000082041692820192909252600160201b90910463ffffffff16928101929092529061171890612c7b565b60ca545f905b63ffffffff811615611b0f578260ca611ac86001846143ca565b63ffffffff1681548110611ade57611ade613f71565b905f5260205f2090600202015f015403611afd576117186001826143ca565b80611b07816143e6565b915050611aae565b5060405163504570e360e01b815260040160405180910390fd5b81611b3381612475565b611b505760405163932d94f760e01b815260040160405180910390fd5b6040516336b87bd760e11b81526001600160a01b0384811660048301527f0000000000000000000000000dcd1bf9a1b36ce34237eeafef220932846bcd821690636d70f7ae90602401602060405180830381865afa158015611bb4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bd89190613f56565b80611c6c575060405163ba1a84e560e01b81526001600160a01b0384811660048301525f917f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed9091169063ba1a84e590602401602060405180830381865afa158015611c46573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c6a9190614404565b115b611c895760405163fb494ea160e01b815260040160405180910390fd5b6110c0838361304b565b611c9b6127ce565b6001600160a01b038116611d055760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6113c181612f3c565b5f54610100900460ff1615808015611d2c57505f54600160ff909116105b80611d455750303b158015611d4557505f5460ff166001145b611da85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611cfc565b5f805460ff191660011790558015611dc9575f805461ff0019166101001790555b611dd2856128cb565b611ddb86612f3c565b611de484612f8d565b611ded83612d28565b611df6826130ae565b8015611e3b575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6008611e4e8161244a565b83611e5881612475565b611e755760405163932d94f760e01b815260040160405180910390fd5b6040516304c1b8eb60e31b81526001600160a01b037f00000000000000000000000068b1d87f95878fe05b998f19b66f4baba5de1aed169063260dc75890611ec1908790600401613f48565b602060405180830381865afa158015611edc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f009190613f56565b611f1d57604051631fb1705560e21b815260040160405180910390fd5b60cb545f90611f3990600160a01b900463ffffffff164261431a565b6001600160a01b0387165f90815260d66020526040812091925090611f6b90826116cf6116ca368b90038b018b614362565b6001600160a01b0388165f90815260d660205260408120919250611fb09190611f9c6116ca368b90038b018b614362565b81526020019081526020015f208684613119565b866001600160a01b0316336001600160a01b03167f14918b3834ab6752eb2e1b489b6663a67810efb5f56f3944a97ede8ecf1fd9f18885858a604051611ff9949392919061441b565b60405180910390a350505050505050565b5f6001610eee6020840184613a33565b60036120258161244a565b60cb546001600160a01b0316331461205057604051635c427cd960e01b815260040160405180910390fd5b60ca5463ffffffff831610612078576040516394a8d38960e01b815260040160405180910390fd5b5f60ca8363ffffffff168154811061209257612092613f71565b905f5260205f20906002020190508060010160089054906101000a900460ff16156120d057604051631b14174b60e01b815260040160405180910390fd5b6001810154600160201b900463ffffffff16421061210157604051630c36f66560e21b815260040160405180910390fd5b60018101805460ff60401b1916600160401b17905560405163ffffffff8416907fd850e6e5dfa497b72661fa73df2923464eaed9dc2ff1d3cb82bccbfeabe5c41e905f90a2505050565b6121536131e8565b6066548019821981161461217a5760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b5f6121c28161244a565b6121ca61251f565b5f5b828110156110b557368484838181106121e7576121e7613f71565b90506020028101906121f99190614250565b335f81815260ce6020908152604080832054905194955093919261222392909185918791016142e2565b60405160208183030381529060405280519060200120905061224483612908565b335f90815260cf602090815260408083208484529091529020805460ff191660019081179091556122769083906141f0565b335f81815260ce602052604090819020929092559051829184917f450a367a380c4e339e5ae7340c8464ef27af7781ad9945cfe8abd828f89e6281906122bd908890614308565b60405180910390a46122de333060408601803590610cf29060208901613a33565b5050506001016121cc565b60046122f48161244a565b335f90815260d1602052604090205460ff1661232357604051635c427cd960e01b815260040160405180910390fd5b61232b61251f565b5f5b828110156110b5573684848381811061234857612348613f71565b905060200281019061235a9190614250565b335f81815260ce6020908152604080832054905194955093919261238492909185918791016142e2565b6040516020818303038152906040528051906020012090506123a583612908565b335f90815260d2602090815260408083208484529091529020805460ff191660019081179091556123d79083906141f0565b335f81815260ce602052604090819020929092559051829184917f5251b6fdefcb5d81144e735f69ea4c695fd43b0289ca53dc075033f5fc80068b9061241e908890614308565b60405180910390a461243f333060408601803590610cf29060208901613a33565b50505060010161232d565b606654600160ff83161b908116036113c15760405163840a48d560e01b815260040160405180910390fd5b604051631beb2b9760e31b81526001600160a01b0382811660048301523360248301523060448301525f80356001600160e01b0319166064840152917f0000000000000000000000003aa5ebb10dc797cac828524e59a333d0a371443c9091169063df595cb8906084016020604051808303815f875af11580156124fb573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137a9190613f56565b6002609754036125715760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611cfc565b6002609755565b5f6125ab612586838061444f565b6125966080860160608701613cc5565b6125a660a0870160808801613cc5565b613299565b5f6125b9604084018461444f565b9050116125d95760405163796cc52560e01b815260040160405180910390fd5b426125ea60a0840160808501613cc5565b6125fa6080850160608601613cc5565b612604919061431a565b63ffffffff16106126285760405163150358a160e21b815260040160405180910390fd5b5f80805b612639604086018661444f565b905081101561272a5736612650604087018761444f565b8381811061266057612660613f71565b6040029190910191505f90506126796020830183613a33565b6001600160a01b0316036126a057604051630863a45360e11b815260040160405180910390fd5b6126ad6020820182613a33565b6001600160a01b0316836001600160a01b0316106126de576040516310fb47f160e31b815260040160405180910390fd5b5f816020013511612702576040516310eb483f60e21b815260040160405180910390fd5b61270f6020820182613a33565b925061271f6020820135856141f0565b93505060010161262c565b506f4b3b4ca85a86c47a098a223fffffffff82111561275c5760405163070b5a6f60e21b815260040160405180910390fd5b5092915050565b6040516001600160a01b038085166024830152831660448201526064810182905261131f9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613597565b6033546001600160a01b031633146113d65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611cfc565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b0316906346fbf68e90602401602060405180830381865afa15801561288a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ae9190613f56565b6113d657604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b612935612915828061444f565b6129256080850160608601613cc5565b6125a660a0860160808701613cc5565b5f816040013511612959576040516310eb483f60e21b815260040160405180910390fd5b6f4b3b4ca85a86c47a098a223fffffffff8160400135111561298e5760405163070b5a6f60e21b815260040160405180910390fd5b6129be63ffffffff7f0000000000000000000000000000000000000000000000000000000000278d0016426141f0565b6129ce6080830160608401613cc5565b63ffffffff1611156113c157604051637ee2b44360e01b815260040160405180910390fd5b5f60ca612a036020850185613cc5565b63ffffffff1681548110612a1957612a19613f71565b5f91825260209182902060408051608081018252600293909302909101805483526001015463ffffffff80821694840194909452600160201b810490931690820152600160401b90910460ff16151560608201529050612a798382612d99565b5f612a8a6080850160608601613a33565b6001600160a01b038082165f90815260cc60205260409020549192501680612aaf5750805b336001600160a01b03821614612ad857604051635c427cd960e01b815260040160405180910390fd5b5f5b612ae760a0870187614494565b9050811015611e3b5736612afe60e088018861444f565b83818110612b0e57612b0e613f71565b6001600160a01b0387165f90815260cd602090815260408083209302949094019450929091508290612b4290850185613a33565b6001600160a01b03166001600160a01b031681526020019081526020015f2054905080826020013511612b885760405163aa385e8160e01b815260040160405180910390fd5b5f612b97826020850135614228565b6001600160a01b0387165f90815260cd60209081526040822092935085018035929190612bc49087613a33565b6001600160a01b031681526020808201929092526040015f2091909155612c059089908390612bf590870187613a33565b6001600160a01b0316919061366a565b86516001600160a01b03808a1691878216918916907f9543dbd55580842586a951f0386e24d68a5df99ae29e3b216588b45fd684ce3190612c496020890189613a33565b604080519283526001600160a01b039091166020830152810186905260600160405180910390a4505050600101612ada565b5f816040015163ffffffff165f1480612cad5750815161ffff908116148015612cad5750816040015163ffffffff1642105b15612cc557505060cb54600160e01b900461ffff1690565b816040015163ffffffff16421015612cde57815161137a565b506020015190565b919050565b60605f612cf78361369a565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b60cb546040805163ffffffff600160a01b9093048316815291831660208301527faf557c6c02c208794817a705609cfa935f827312a1adfdd26494b6b95dd2b4b3910160405180910390a160cb805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b806060015115612dbc57604051631b14174b60e01b815260040160405180910390fd5b806040015163ffffffff16421015612de757604051631437a2bb60e31b815260040160405180910390fd5b612df460c0830183614494565b9050612e0360a0840184614494565b905014612e23576040516343714afd60e01b815260040160405180910390fd5b612e3060e083018361444f565b9050612e3f60c0840184614494565b905014612e5f576040516343714afd60e01b815260040160405180910390fd5b8051612e8b90612e756040850160208601613cc5565b612e8260408601866144d9565b866060016136c1565b5f5b612e9a60a0840184614494565b90508110156110c057612f346080840135612eb860a0860186614494565b84818110612ec857612ec8613f71565b9050602002016020810190612edd9190613cc5565b612eea60c0870187614494565b85818110612efa57612efa613f71565b9050602002810190612f0c91906144d9565b612f1960e089018961444f565b87818110612f2957612f29613f71565b905060400201613765565b600101612e8d565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60cb546040516001600160a01b038084169216907f237b82f438d75fc568ebab484b75b01d9287b9e98b490b7c23221623b6705dbb905f90a360cb80546001600160a01b0319166001600160a01b0392909216919091179055565b5f815f0151826020015163ffffffff1660405160200161303392919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b60405160208183030381529060405261137a9061451b565b6001600160a01b038083165f81815260cc602052604080822080548686166001600160a01b0319821681179092559151919094169392849290917fbab947934d42e0ad206f25c9cab18b5bb6ae144acfb00f40b4e3aa59590ca3129190a4505050565b60cb546040805161ffff600160e01b9093048316815291831660208301527fe6cd4edfdcc1f6d130ab35f73d72378f3a642944fb4ee5bd84b7807a81ea1c4e910160405180910390a160cb805461ffff909216600160e01b0261ffff60e01b19909216919091179055565b61271061ffff831611156131405760405163891c63df60e01b815260040160405180910390fd5b8254600160201b900463ffffffff16421161316e57604051637b1e25c560e01b815260040160405180910390fd5b8254600160201b900463ffffffff165f0361319557825461ffff191661ffff1783556131ac565b825462010000810461ffff1661ffff199091161783555b825463ffffffff909116600160201b0267ffffffff000000001961ffff90931662010000029290921667ffffffffffff00001990911617179055565b7f000000000000000000000000b7f8bc63bbcad18155201308c8f3540b07f84f5e6001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613244573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613268919061453e565b6001600160a01b0316336001600160a01b0316146113d65760405163794821ff60e01b815260040160405180910390fd5b826132b75760405163796cc52560e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000005c490063ffffffff168163ffffffff16111561330457604051630dd0b9f560e21b815260040160405180910390fd5b61332e7f00000000000000000000000000000000000000000000000000000000000151808261456d565b63ffffffff16156133525760405163ee66470560e01b815260040160405180910390fd5b5f8163ffffffff16116133785760405163cb3f434d60e01b815260040160405180910390fd5b6133a27f00000000000000000000000000000000000000000000000000000000000151808361456d565b63ffffffff16156133c657604051633c1a94f160e21b815260040160405180910390fd5b8163ffffffff167f000000000000000000000000000000000000000000000000000000000076a70063ffffffff16426133ff9190614228565b1115801561343957508163ffffffff167f0000000000000000000000000000000000000000000000000000000065fb788063ffffffff1611155b6134565760405163041aa75760e11b815260040160405180910390fd5b5f805b84811015611e3b575f86868381811061347457613474613f71565b61348a9260206040909202019081019150613a33565b60405163198f077960e21b81526001600160a01b0380831660048301529192507f0000000000000000000000009a676e781a523b5d0c0e43731313a708cb6075089091169063663c1de490602401602060405180830381865afa1580156134f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135179190613f56565b8061353e57506001600160a01b03811673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0145b61355b57604051632efd965160e11b815260040160405180910390fd5b806001600160a01b0316836001600160a01b03161061358d5760405163dfad9ca160e01b815260040160405180910390fd5b9150600101613459565b5f6135eb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137a39092919063ffffffff16565b905080515f148061360b57508080602001905181019061360b9190613f56565b6110c05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611cfc565b6040516001600160a01b0383166024820152604481018290526110c090849063a9059cbb60e01b90606401612797565b5f60ff8216601f81111561137a57604051632cd44ac360e21b815260040160405180910390fd5b6136cc602083614594565b6001901b8463ffffffff16106136f45760405162c6c39d60e71b815260040160405180910390fd5b5f6136fe82610edf565b905061374884848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508a92508591505063ffffffff89166137b9565b611e3b576040516369ca16c960e01b815260040160405180910390fd5b613770602083614594565b6001901b8463ffffffff16106137995760405163054ff4df60e51b815260040160405180910390fd5b5f6136fe8261200a565b60606137b184845f856137ee565b949350505050565b5f836137d8576040516329e7276760e11b815260040160405180910390fd5b836137e48685856138c5565b1495945050505050565b60608247101561384f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611cfc565b5f5f866001600160a01b0316858760405161386a91906145a7565b5f6040518083038185875af1925050503d805f81146138a4576040519150601f19603f3d011682016040523d82523d5f602084013e6138a9565b606091505b50915091506138ba87838387613982565b979650505050505050565b5f83515f036138d5575081611718565b602084516138e391906145bd565b15613901576040516313717da960e21b815260040160405180910390fd5b8260205b85518111613962576139186002856145bd565b5f0361393957815f528086015160205260405f209150600284049350613950565b808601515f528160205260405f2091506002840493505b61395b6020826141f0565b9050613905565b5082156137b1576040516363df817160e01b815260040160405180910390fd5b606083156139f05782515f036139e9576001600160a01b0385163b6139e95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611cfc565b50816137b1565b6137b18383815115613a055781518083602001fd5b8060405162461bcd60e51b8152600401611cfc9190613c90565b6001600160a01b03811681146113c1575f5ffd5b5f60208284031215613a43575f5ffd5b813561171881613a1f565b5f60408284031215613a5e575f5ffd5b50919050565b5f5f83601f840112613a74575f5ffd5b5081356001600160401b03811115613a8a575f5ffd5b6020830191508360208260051b8501011115613aa4575f5ffd5b9250929050565b5f5f5f60608486031215613abd575f5ffd5b613ac78585613a4e565b925060408401356001600160401b03811115613ae1575f5ffd5b613aed86828701613a64565b9497909650939450505050565b80151581146113c1575f5ffd5b5f5f60408385031215613b18575f5ffd5b8235613b2381613a1f565b91506020830135613b3381613afa565b809150509250929050565b5f60208284031215613b4e575f5ffd5b5035919050565b5f60408284031215613b65575f5ffd5b6117188383613a4e565b5f5f60208385031215613b80575f5ffd5b82356001600160401b03811115613b95575f5ffd5b613ba185828601613a64565b90969095509350505050565b5f6101008284031215613a5e575f5ffd5b5f5f60408385031215613bcf575f5ffd5b82356001600160401b03811115613be4575f5ffd5b613bf085828601613bad565b9250506020830135613b3381613a1f565b803563ffffffff81168114612ce6575f5ffd5b5f5f60408385031215613c25575f5ffd5b82359150613c3560208401613c01565b90509250929050565b5f5f5f60408486031215613c50575f5ffd5b83356001600160401b03811115613c65575f5ffd5b613c7186828701613a64565b9094509250506020840135613c8581613a1f565b809150509250925092565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215613cd5575f5ffd5b61171882613c01565b5f60208284031215613cee575f5ffd5b813560ff81168114611718575f5ffd5b5f60208284031215613d0e575f5ffd5b81356001600160401b03811115613d23575f5ffd5b6137b184828501613bad565b5f5f60408385031215613d40575f5ffd5b8235613d4b81613a1f565b946020939093013593505050565b5f5f60408385031215613d6a575f5ffd5b8235613d7581613a1f565b91506020830135613b3381613a1f565b5f5f5f60408486031215613d97575f5ffd5b8335613da281613a1f565b925060208401356001600160401b03811115613ae1575f5ffd5b5f5f60608385031215613dcd575f5ffd5b8235613dd881613a1f565b9150613c358460208501613a4e565b803561ffff81168114612ce6575f5ffd5b5f60208284031215613e08575f5ffd5b61171882613de7565b5f5f60408385031215613e22575f5ffd5b8235613e2d81613a1f565b9150613c3560208401613de7565b5f5f5f60608486031215613e4d575f5ffd5b8335613e5881613a1f565b92506020840135613e6881613a1f565b9150613e7660408501613de7565b90509250925092565b5f5f5f5f5f60a08688031215613e93575f5ffd5b8535613e9e81613a1f565b9450602086013593506040860135613eb581613a1f565b9250613ec360608701613c01565b9150613ed160808701613de7565b90509295509295909350565b5f5f5f60808486031215613eef575f5ffd5b8335613efa81613a1f565b9250613f098560208601613a4e565b9150613e7660608501613de7565b8035613f2281613a1f565b6001600160a01b0316825263ffffffff613f3e60208301613c01565b1660208301525050565b6040810161137a8284613f17565b5f60208284031215613f66575f5ffd5b815161171881613afa565b634e487b7160e01b5f52603260045260245ffd5b5f823560be19833603018112613f99575f5ffd5b9190910192915050565b5f5f8335601e19843603018112613fb8575f5ffd5b83016020810192503590506001600160401b03811115613fd6575f5ffd5b8060061b3603821315613aa4575f5ffd5b8183526020830192505f815f5b8481101561404a57813561400781613a1f565b6001600160a01b0316865260208201356bffffffffffffffffffffffff8116808214614031575f5ffd5b6020880152506040958601959190910190600101613ff4565b5093949350505050565b5f5f8335601e19843603018112614069575f5ffd5b83016020810192503590506001600160401b03811115614087575f5ffd5b803603821315613aa4575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f6140c88283613fa3565b60c085526140da60c086018284613fe7565b91505060208301356140eb81613a1f565b6001600160a01b031660208501526141066040840184613fa3565b858303604087015280835290915f91906020015b8183101561415557833561412d81613a1f565b6001600160a01b0316815260208481013590820152604093840193600193909301920161411a565b61416160608701613c01565b63ffffffff81166060890152935061417b60808701613c01565b63ffffffff81166080890152935061419660a0870187614054565b9450925086810360a08801526138ba818585614095565b60018060a01b0384168152826020820152606060408201525f6141d360608301846140bd565b95945050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561137a5761137a6141dc565b61420d8185613f17565b826040820152608060608201525f6141d360808301846140bd565b8181038181111561137a5761137a6141dc565b5f81614249576142496141dc565b505f190190565b5f8235609e19833603018112613f99575f5ffd5b5f61426f8283613fa3565b60a0855261428160a086018284613fe7565b915050602083013561429281613a1f565b6001600160a01b031660208501526040838101359085015263ffffffff6142bb60608501613c01565b16606085015263ffffffff6142d260808501613c01565b1660808501528091505092915050565b60018060a01b0384168152826020820152606060408201525f6141d36060830184614264565b602081525f6117186020830184614264565b63ffffffff818116838216019081111561137a5761137a6141dc565b5f823560fe19833603018112613f99575f5ffd5b828152604060208201525f6137b160408301846140bd565b5f6040828403128015614373575f5ffd5b50604080519081016001600160401b03811182821017156143a257634e487b7160e01b5f52604160045260245ffd5b60405282356143b081613a1f565b81526143be60208401613c01565b60208201529392505050565b63ffffffff828116828216039081111561137a5761137a6141dc565b5f63ffffffff8216806143fb576143fb6141dc565b5f190192915050565b5f60208284031215614414575f5ffd5b5051919050565b60a081016144298287613f17565b63ffffffff94909416604082015261ffff92831660608201529116608090910152919050565b5f5f8335601e19843603018112614464575f5ffd5b8301803591506001600160401b0382111561447d575f5ffd5b6020019150600681901b3603821315613aa4575f5ffd5b5f5f8335601e198436030181126144a9575f5ffd5b8301803591506001600160401b038211156144c2575f5ffd5b6020019150600581901b3603821315613aa4575f5ffd5b5f5f8335601e198436030181126144ee575f5ffd5b8301803591506001600160401b03821115614507575f5ffd5b602001915036819003821315613aa4575f5ffd5b80516020808301519190811015613a5e575f1960209190910360031b1b16919050565b5f6020828403121561454e575f5ffd5b815161171881613a1f565b634e487b7160e01b5f52601260045260245ffd5b5f63ffffffff83168061458257614582614559565b8063ffffffff84160691505092915050565b5f826145a2576145a2614559565b500490565b5f82518060208501845e5f920191825250919050565b5f826145cb576145cb614559565b50069056fea26469706673582212209764e0fe3693a179c5f7a81fc907220c85c1a49189bc26fd152ee3a6c5a36b1e64736f6c634300081c0033000000000000000000", + "address": "0x0000F90827F1C53a10cb7A02335B175320002935", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500", + "storage": {} + }, + "1": { + "address": "0x1111111111111111111111111111111111111111", + "code": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80632baeceb71461004e5780638381f58a146100585780638da5cb5b14610073578063d826f88f1461009e575b5f5ffd5b6100566100a6565b005b6100605f5481565b6040519081526020015b60405180910390f35b600154610086906001600160a01b031681565b6040516001600160a01b03909116815260200161006a565b61005661010d565b5f5f54116100fb5760405162461bcd60e51b815260206004820152601f60248201527f4e756d6265722073686f756c642062652067726561746572207468616e20300060448201526064015b60405180910390fd5b60015f54610109919061016d565b5f55565b6001546001600160a01b031633146101675760405162461bcd60e51b815260206004820152601760248201527f4f6e6c792063616c6c61626c65206279206f776e65722100000000000000000060448201526064016100f2565b600a5f55565b8181038181111561018c57634e487b7160e01b5f52601160045260245ffd5b9291505056fea2646970667358221220ac5899491afd834afd223fd632497d1c0c7593961eda22f04c58db4b504999cf64736f6c634300081c0033000000", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000000000000000000000000000000000000000000ff" + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" } }, - "8": { - "address": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF", - "code": "0x60806040526004361061003e575f3560e01c806305b1137b1461004257806325ccedec14610063578063c6b295c114610082578063d0e30db014610061575b5f5ffd5b34801561004d575f5ffd5b5061006161005c36600461025e565b6100a1565b005b34801561006e575f5ffd5b5061006161007d366004610288565b6100b8565b34801561008d575f5ffd5b5061006161009c3660046102ef565b6100da565b6100b46001600160a01b038316826100f7565b5050565b6100d56001600160a01b038416836001600160801b038416610120565b505050565b5f6100e6848484610171565b9050806100f1575f5ffd5b50505050565b5f5f5f5f5f85875af19050806100d557604051633d2cec6f60e21b815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526100d590849060640160408051601f198184030181529190526020810180516001600160e01b031663a9059cbb60e01b179052610188565b5f5f5f5f85516020870186895af195945050505050565b5f5f836001600160a01b0316836040516101a291906103be565b5f604051808303815f865af19150503d805f81146101db576040519150601f19603f3d011682016040523d82523d5f602084013e6101e0565b606091505b50915091505f82801561020b57508151158061020b57508180602001905181019061020b91906103d4565b905080158061022257506001600160a01b0385163b155b156102405760405163022e258160e11b815260040160405180910390fd5b5050505050565b6001600160a01b038116811461025b575f5ffd5b50565b5f5f6040838503121561026f575f5ffd5b823561027a81610247565b946020939093013593505050565b5f5f5f6060848603121561029a575f5ffd5b83356102a581610247565b925060208401356102b581610247565b915060408401356001600160801b03811681146102d0575f5ffd5b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f60608486031215610301575f5ffd5b833561030c81610247565b9250602084013567ffffffffffffffff811115610327575f5ffd5b8401601f81018613610337575f5ffd5b803567ffffffffffffffff811115610351576103516102db565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610380576103806102db565b604052818152828201602001881015610397575f5ffd5b816020840160208301375f9181016020019190915293969395505050506040919091013590565b5f82518060208501845e5f920191825250919050565b5f602082840312156103e4575f5ffd5b815180151581146103f3575f5ffd5b939250505056fea2646970667358221220590055fea5441ad6e827390b16005643886d2dc4ffe2b97b43ed3ab207076ab664736f6c634300081c003300", + "4": { + "address": "0x0000BBdDc7CE488642fb579F8B00f3a590007251", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd00", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + } + }, + "5": { + "address": "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", "storage": {} } } diff --git a/contracts/foundry.lock b/contracts/foundry.lock new file mode 100644 index 00000000..1a3a4fb3 --- /dev/null +++ b/contracts/foundry.lock @@ -0,0 +1,11 @@ +{ + "lib/eigenlayer-contracts": { + "rev": "7ecc83c7b180850531bc5b8b953a7340adeecd43" + }, + "lib/forge-std": { + "rev": "9530d9ec702df1b27b7f8f50c0a63a11b1b5fba9" + }, + "lib/snowbridge": { + "rev": "13263fefa29a3f4af50e5650dcd93fe3afac44db" + } +} \ No newline at end of file diff --git a/contracts/script/deploy/Config.sol b/contracts/script/deploy/Config.sol index c23c8804..63558988 100644 --- a/contracts/script/deploy/Config.sol +++ b/contracts/script/deploy/Config.sol @@ -8,7 +8,9 @@ contract Config { uint256 randaoCommitExpiration; uint256 minNumRequiredSignatures; uint64 startBlock; + uint128 initialValidatorSetId; bytes32[] initialValidatorHashes; + uint128 nextValidatorSetId; bytes32[] nextValidatorHashes; bytes32 rewardsMessageOrigin; } @@ -17,9 +19,8 @@ contract Config { struct AVSConfig { address avsOwner; address rewardsInitiator; - address vetoCommitteeMember; - uint32 vetoWindowBlocks; address[] validatorsStrategies; + address validatorSetSubmitter; } // EigenLayer parameters diff --git a/contracts/script/deploy/DeployBase.s.sol b/contracts/script/deploy/DeployBase.s.sol index 67cfa7af..39b4ec34 100644 --- a/contracts/script/deploy/DeployBase.s.sol +++ b/contracts/script/deploy/DeployBase.s.sol @@ -32,6 +32,10 @@ import { } from "eigenlayer-contracts/src/contracts/permissions/PermissionController.sol"; import {EigenPodManager} from "eigenlayer-contracts/src/contracts/pods/EigenPodManager.sol"; import {IETHPOSDeposit} from "eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import { + IRewardsCoordinatorTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; // DataHaven imports import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol"; @@ -41,8 +45,9 @@ import {ValidatorsUtils} from "../../script/utils/ValidatorsUtils.sol"; struct ServiceManagerInitParams { address avsOwner; address rewardsInitiator; - address[] validatorsStrategies; + IRewardsCoordinatorTypes.StrategyAndMultiplier[] validatorsStrategiesAndMultipliers; address gateway; + address validatorSetSubmitter; } // Struct to store more detailed strategy information @@ -208,10 +213,12 @@ abstract contract DeployBase is Script, DeployParams, Accounts { SnowbridgeConfig memory config ) internal returns (BeefyClient) { // Create validator sets using the MerkleUtils library - BeefyClient.ValidatorSet memory validatorSet = - ValidatorsUtils._buildValidatorSet(0, config.initialValidatorHashes); - BeefyClient.ValidatorSet memory nextValidatorSet = - ValidatorsUtils._buildValidatorSet(1, config.nextValidatorHashes); + BeefyClient.ValidatorSet memory validatorSet = ValidatorsUtils._buildValidatorSet( + config.initialValidatorSetId, config.initialValidatorHashes + ); + BeefyClient.ValidatorSet memory nextValidatorSet = ValidatorsUtils._buildValidatorSet( + config.nextValidatorSetId, config.nextValidatorHashes + ); // Deploy BeefyClient vm.broadcast(_deployerPrivateKey); @@ -243,12 +250,23 @@ abstract contract DeployBase is Script, DeployParams, Accounts { "ServiceManager Implementation", address(serviceManagerImplementation) ); + // Build StrategyAndMultiplier[] from config addresses with default multiplier of 1. + // Multipliers can be updated post-deployment via setStrategiesAndMultipliers if needed. + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory strategiesAndMultipliers = new IRewardsCoordinatorTypes + .StrategyAndMultiplier[](avsConfig.validatorsStrategies.length); + for (uint256 i = 0; i < avsConfig.validatorsStrategies.length; i++) { + strategiesAndMultipliers[i] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: IStrategy(avsConfig.validatorsStrategies[i]), multiplier: 1 + }); + } + // Create service manager initialisation parameters struct ServiceManagerInitParams memory initParams = ServiceManagerInitParams({ avsOwner: avsConfig.avsOwner, rewardsInitiator: avsConfig.rewardsInitiator, - validatorsStrategies: avsConfig.validatorsStrategies, - gateway: address(gateway) + validatorsStrategiesAndMultipliers: strategiesAndMultipliers, + gateway: address(gateway), + validatorSetSubmitter: avsConfig.validatorSetSubmitter }); // Create the service manager proxy (different logic for local vs testnet) diff --git a/contracts/script/deploy/DeployTestnet.s.sol b/contracts/script/deploy/DeployLive.s.sol similarity index 84% rename from contracts/script/deploy/DeployTestnet.s.sol rename to contracts/script/deploy/DeployLive.s.sol index bbacd594..e05b017c 100644 --- a/contracts/script/deploy/DeployTestnet.s.sol +++ b/contracts/script/deploy/DeployLive.s.sol @@ -29,10 +29,11 @@ import { } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; /** - * @title DeployTestnet - * @notice Deployment script for testnets (hoodi) - references existing EigenLayer contracts + * @title DeployLive + * @notice Deployment script for live networks (hoodi testnet, ethereum mainnet) + * @dev References existing EigenLayer contracts on the target chain */ -contract DeployTestnet is DeployBase { +contract DeployLive is DeployBase { string public networkName; function run() public { @@ -40,7 +41,7 @@ contract DeployTestnet is DeployBase { networkName = vm.envString("NETWORK"); require( bytes(networkName).length > 0, - "NETWORK environment variable required for testnet deployment" + "NETWORK environment variable required for live deployment" ); _validateNetwork(networkName); @@ -49,7 +50,7 @@ contract DeployTestnet is DeployBase { address avsOwnerEnv = vm.envOr("AVS_OWNER_ADDRESS", address(0)); require( avsOwnerEnv != address(0), - "AVS_OWNER_ADDRESS env variable required for testnet deployments" + "AVS_OWNER_ADDRESS env variable required for live deployments" ); _executeSharedDeployment(); @@ -60,8 +61,8 @@ contract DeployTestnet is DeployBase { return networkName; } - function _getDeploymentMode() internal pure override returns (string memory) { - return "HOODI_TESTNET"; + function _getDeploymentMode() internal view override returns (string memory) { + return string.concat("LIVE_", networkName); } function _setupEigenLayerContracts( @@ -100,16 +101,16 @@ contract DeployTestnet is DeployBase { Logging.logStep("All EigenLayer contracts referenced successfully"); Logging.logFooter(); - // Testnet deployments create their own ProxyAdmin (no existing one from EigenLayer deployment) + // Live deployments create their own ProxyAdmin (no existing one from EigenLayer deployment) return ProxyAdmin(address(0)); // Will be created in _createServiceManagerProxy } function _createServiceManagerProxy( DataHavenServiceManager implementation, - ProxyAdmin, // Ignored for testnet deployment + ProxyAdmin, // Ignored for live deployment ServiceManagerInitParams memory params ) internal override returns (DataHavenServiceManager) { - // Testnet deployment creates its own ProxyAdmin for the service manager + // Live deployment creates its own ProxyAdmin for the service manager vm.broadcast(_deployerPrivateKey); ProxyAdmin proxyAdmin = new ProxyAdmin(); Logging.logContractDeployed("ProxyAdmin", address(proxyAdmin)); @@ -119,8 +120,9 @@ contract DeployTestnet is DeployBase { DataHavenServiceManager.initialize.selector, params.avsOwner, params.rewardsInitiator, - params.validatorsStrategies, - params.gateway + params.validatorsStrategiesAndMultipliers, + params.gateway, + params.validatorSetSubmitter ); TransparentUpgradeableProxy proxy = @@ -186,7 +188,7 @@ contract DeployTestnet is DeployBase { ); json = string.concat(json, '"RewardsAgent": "', vm.toString(rewardsAgent), '",'); - // EigenLayer contracts (existing on testnet) + // EigenLayer contracts (existing on live network) json = string.concat(json, '"DelegationManager": "', vm.toString(address(delegation)), '",'); json = string.concat( json, '"StrategyManager": "', vm.toString(address(strategyManager)), '",' @@ -209,23 +211,34 @@ contract DeployTestnet is DeployBase { Logging.logInfo(string.concat("Deployment info saved to: ", deploymentPath)); } - // TESTNET-SPECIFIC FUNCTIONS + // LIVE DEPLOYMENT FUNCTIONS /** - * @notice Validate that the network is hoodi (the only supported testnet) + * @notice Validate that the network is in the supported allowlist + * @dev Supported networks: + * - "hoodi", "stagenet-hoodi", "testnet-hoodi" (Hoodi testnet) + * - "ethereum", "mainnet-ethereum" (Ethereum mainnet) */ function _validateNetwork( string memory network ) internal pure { - bytes32 networkHash = keccak256(abi.encodePacked(network)); + bytes32 h = keccak256(bytes(network)); - if (networkHash != keccak256(abi.encodePacked("hoodi"))) { - revert( - string.concat( - "Unsupported testnet network: ", network, ". Supported networks: hoodi" - ) - ); + if ( + h == keccak256("hoodi") || h == keccak256("stagenet-hoodi") + || h == keccak256("testnet-hoodi") || h == keccak256("mainnet-ethereum") + || h == keccak256("ethereum") + ) { + return; } + + revert( + string.concat( + "Unsupported network: ", + network, + ". Supported: hoodi, stagenet-hoodi, testnet-hoodi, ethereum, mainnet-ethereum" + ) + ); } /** diff --git a/contracts/script/deploy/DeployLocal.s.sol b/contracts/script/deploy/DeployLocal.s.sol index 8d122912..8706f9f4 100644 --- a/contracts/script/deploy/DeployLocal.s.sol +++ b/contracts/script/deploy/DeployLocal.s.sol @@ -206,8 +206,9 @@ contract DeployLocal is DeployBase { DataHavenServiceManager.initialize.selector, params.avsOwner, params.rewardsInitiator, - params.validatorsStrategies, - params.gateway + params.validatorsStrategiesAndMultipliers, + params.gateway, + params.validatorSetSubmitter ); TransparentUpgradeableProxy proxy = @@ -355,11 +356,15 @@ contract DeployLocal is DeployBase { function _prepareStrategiesForServiceManager( ServiceManagerInitParams memory params ) internal view { - if (params.validatorsStrategies.length == 0) { - params.validatorsStrategies = new address[](deployedStrategies.length); + if (params.validatorsStrategiesAndMultipliers.length == 0) { + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](deployedStrategies.length); for (uint256 i = 0; i < deployedStrategies.length; i++) { - params.validatorsStrategies[i] = deployedStrategies[i].address_; + sm[i] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: IStrategy(deployedStrategies[i].address_), multiplier: 1 + }); } + params.validatorsStrategiesAndMultipliers = sm; } } diff --git a/contracts/script/deploy/DeployParams.s.sol b/contracts/script/deploy/DeployParams.s.sol index 4bdbb284..eda4630f 100644 --- a/contracts/script/deploy/DeployParams.s.sol +++ b/contracts/script/deploy/DeployParams.s.sol @@ -31,9 +31,27 @@ contract DeployParams is Script, Config { bool isDevMode = keccak256(abi.encodePacked(vm.envOr("DEV_MODE", string("false")))) == keccak256(abi.encodePacked("true")); if (isDevMode) { + config.initialValidatorSetId = 0; config.initialValidatorHashes = TestUtils.generateMockValidators(10); + config.nextValidatorSetId = 1; config.nextValidatorHashes = TestUtils.generateMockValidators(10); } else { + // Load validator set IDs (default to 0/1 for backwards compatibility) + try vm.parseJsonUint(configJson, ".snowbridge.initialValidatorSetId") returns ( + uint256 val + ) { + config.initialValidatorSetId = uint128(val); + } catch { + config.initialValidatorSetId = 0; + } + try vm.parseJsonUint(configJson, ".snowbridge.nextValidatorSetId") returns ( + uint256 val + ) { + config.nextValidatorSetId = uint128(val); + } catch { + config.nextValidatorSetId = config.initialValidatorSetId + 1; + } + config.initialValidatorHashes = _loadValidatorsFromConfig(configJson, ".snowbridge.initialValidatorHashes"); config.nextValidatorHashes = @@ -58,11 +76,15 @@ contract DeployParams is Script, Config { config.avsOwner = vm.parseJsonAddress(configJson, ".avs.avsOwner"); } config.rewardsInitiator = vm.parseJsonAddress(configJson, ".avs.rewardsInitiator"); - config.vetoCommitteeMember = vm.parseJsonAddress(configJson, ".avs.vetoCommitteeMember"); - config.vetoWindowBlocks = vm.parseJsonUint(configJson, ".avs.vetoWindowBlocks").toUint32(); config.validatorsStrategies = vm.parseJsonAddressArray(configJson, ".avs.validatorsStrategies"); + try vm.parseJsonAddress(configJson, ".avs.validatorSetSubmitter") returns (address addr) { + config.validatorSetSubmitter = addr; + } catch { + config.validatorSetSubmitter = address(0); + } + return config; } diff --git a/contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol b/contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol new file mode 100644 index 00000000..ffaa0018 --- /dev/null +++ b/contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.27; + +import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; + +import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol"; + +/// @notice Test-only fixture contract with intentionally broken storage layout. +/// @dev This contract is used to validate the snapshot-diff storage layout check fails as expected. +contract DataHavenServiceManagerBadLayout is OwnableUpgradeable { + // Deliberate layout shift: inserted before all original state vars + uint256 public layoutBreaker; + + // Original variables (shifted by one slot) + address public rewardsInitiator; + mapping(address => bool) public validatorsAllowlist; + IGatewayV2 private _snowbridgeGateway; + mapping(address => address) public validatorEthAddressToSolochainAddress; + mapping(address => address) public validatorSolochainAddressToEthAddress; + + // Keep the original gap size to mirror shape, despite the shift + uint256[45] private __GAP; + + // Keep a compatible constructor signature for upgrade tests. + constructor( + address, + address + ) { + _disableInitializers(); + } +} + diff --git a/contracts/script/transact/AllocateOperatorStake.s.sol b/contracts/script/transact/AllocateOperatorStake.s.sol new file mode 100644 index 00000000..6372e9fd --- /dev/null +++ b/contracts/script/transact/AllocateOperatorStake.s.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.27; + +// EigenLayer imports +import { + IAllocationManagerTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; + +// Testing imports +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {Logging} from "../utils/Logging.sol"; +import {ELScriptStorage} from "../utils/ELScriptStorage.s.sol"; +import {DHScriptStorage} from "../utils/DHScriptStorage.s.sol"; +import {Accounts} from "../utils/Accounts.sol"; + +/** + * @title AllocateOperatorStake + * @notice Allocates full magnitude to the validator operator set. + * Must be run AFTER SignUpValidator (needs at least 1 block gap + * for the allocation delay to initialize). + */ +contract AllocateOperatorStake is Script, ELScriptStorage, DHScriptStorage, Accounts { + function run() public { + string memory network = vm.envOr("NETWORK", string("anvil")); + Logging.logHeader("ALLOCATE OPERATOR STAKE"); + console.log("| Network: %s", network); + Logging.logFooter(); + + _loadELContracts(network); + _loadDHContracts(network); + + IStrategy[] memory strategies = new IStrategy[](deployedStrategies.length); + for (uint256 i = 0; i < deployedStrategies.length; i++) { + strategies[i] = IStrategy(address(deployedStrategies[i].strategy)); + } + + uint64[] memory newMagnitudes = new uint64[](strategies.length); + for (uint256 i = 0; i < strategies.length; i++) { + newMagnitudes[i] = 1e18; + } + + IAllocationManagerTypes.AllocateParams[] memory allocParams = + new IAllocationManagerTypes.AllocateParams[](1); + allocParams[0] = IAllocationManagerTypes.AllocateParams({ + operatorSet: OperatorSet({ + avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID() + }), + strategies: strategies, + newMagnitudes: newMagnitudes + }); + + vm.broadcast(_operatorPrivateKey); + allocationManager.modifyAllocations(_operator, allocParams); + Logging.logStep( + string.concat("Allocated full magnitude for operator: ", vm.toString(_operator)) + ); + } +} diff --git a/contracts/scripts/check-storage-layout-negative.sh b/contracts/scripts/check-storage-layout-negative.sh new file mode 100755 index 00000000..be79ba9b --- /dev/null +++ b/contracts/scripts/check-storage-layout-negative.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -euo pipefail + +# Negative check: ensure the snapshot-diff storage layout script fails when the layout is broken. + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." + +set +e +OUTPUT="$( + CONTRACT="DataHavenServiceManagerBadLayout" \ + SNAPSHOT="storage-snapshots/DataHavenServiceManager.storage.json" \ + ./scripts/check-storage-layout.sh 2>&1 +)" +EXIT_CODE=$? +set -e + +if [ "$EXIT_CODE" -eq 0 ]; then + echo "ERROR: Expected storage layout check to fail for DataHavenServiceManagerBadLayout, but it succeeded." + exit 1 +fi + +if ! printf '%s\n' "$OUTPUT" | grep -qE "ERROR: (Storage layout has changed!|__GAP invariant violated!)"; then + echo "ERROR: Storage layout check failed, but not for the expected reason." + echo "" + echo "Output:" + echo "$OUTPUT" + exit 1 +fi + +echo "Negative check OK: storage layout check failed as expected for DataHavenServiceManagerBadLayout." + diff --git a/contracts/scripts/check-storage-layout.sh b/contracts/scripts/check-storage-layout.sh new file mode 100755 index 00000000..895dbdb8 --- /dev/null +++ b/contracts/scripts/check-storage-layout.sh @@ -0,0 +1,84 @@ +#!/bin/bash +set -e + +# Storage Layout Check Script +# Compares current storage layout against committed snapshot to detect unintended changes. + +CONTRACT="${CONTRACT:-DataHavenServiceManager}" +SNAPSHOT_DIR="${SNAPSHOT_DIR:-storage-snapshots}" +SNAPSHOT="${SNAPSHOT:-${SNAPSHOT_DIR}/${CONTRACT}.storage.json}" + +# Ensure we're in the contracts directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." + +# Check if snapshot exists +if [ ! -f "$SNAPSHOT" ]; then + echo "ERROR: Snapshot file not found: $SNAPSHOT" + echo "Generate it with: mkdir -p $SNAPSHOT_DIR && forge inspect $CONTRACT storage --json > $SNAPSHOT" + exit 1 +fi + +# Generate current layout +echo "Generating current storage layout for $CONTRACT..." +forge inspect "$CONTRACT" storage --json > /tmp/current_layout.json + +# Normalize both files for comparison: +# - Remove astId (changes with compiler runs) +# - Remove contract field (contains full path) +# - Remove types section (contains unstable AST IDs) +# - Sort by slot number +normalize_json() { + jq 'del(.types) + | .storage + | map( + del(.astId, .contract) + # Remove unstable AST IDs from type strings (e.g., t_contract(IGatewayV2)12345, nested mappings) + | .type |= gsub("\\)[0-9]+"; ")") + ) + | sort_by(.slot | tonumber)' "$1" +} + +echo "Comparing storage layouts..." +normalize_json "$SNAPSHOT" > /tmp/snap_normalized.json +normalize_json /tmp/current_layout.json > /tmp/curr_normalized.json + +if ! diff -q /tmp/snap_normalized.json /tmp/curr_normalized.json > /dev/null 2>&1; then + echo "" + echo "==========================================" + echo "ERROR: Storage layout has changed!" + echo "==========================================" + echo "" + echo "Differences found:" + diff /tmp/snap_normalized.json /tmp/curr_normalized.json || true + echo "" + echo "If this change is intentional, update the snapshot:" + echo " forge inspect $CONTRACT storage --json > $SNAPSHOT" + echo "" + echo "WARNING: Unintended storage layout changes can corrupt state during upgrades!" + exit 1 +fi + +# Verify gap invariant: __GAP slot + array size must equal a fixed constant. +# This catches cases where a new variable is added but __GAP is not shrunk accordingly. +EXPECTED_GAP_TOTAL=151 +GAP_SLOT=$(jq '.storage[] | select(.label == "__GAP") | .slot | tonumber' /tmp/current_layout.json) +GAP_SIZE=$(jq -r '.storage[] | select(.label == "__GAP") | .type' /tmp/current_layout.json \ + | grep -oE '[0-9]+' | tail -1) + +if [ -n "$GAP_SLOT" ] && [ -n "$GAP_SIZE" ]; then + GAP_TOTAL=$((GAP_SLOT + GAP_SIZE)) + if [ "$GAP_TOTAL" -ne "$EXPECTED_GAP_TOTAL" ]; then + echo "" + echo "==========================================" + echo "ERROR: __GAP invariant violated!" + echo "==========================================" + echo "" + echo " slot($GAP_SLOT) + size($GAP_SIZE) = $GAP_TOTAL, expected $EXPECTED_GAP_TOTAL" + echo "" + echo "If you added a new state variable, shrink __GAP by the same number of slots." + exit 1 + fi +fi + +echo "Storage layout OK - no changes detected" diff --git a/contracts/src/DataHavenServiceManager.sol b/contracts/src/DataHavenServiceManager.sol index 414641df..2bf89822 100644 --- a/contracts/src/DataHavenServiceManager.sol +++ b/contracts/src/DataHavenServiceManager.sol @@ -42,6 +42,9 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave /// @notice The EigenLayer operator set ID for the Validators securing the DataHaven network. uint32 public constant VALIDATORS_SET_ID = 0; + /// @notice Maximum number of active validators in the set + uint32 public constant MAX_ACTIVE_VALIDATORS = 32; + // ============ Immutables ============ /// @notice The EigenLayer AllocationManager contract @@ -64,9 +67,17 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave /// @inheritdoc IDataHavenServiceManager mapping(address => address) public validatorEthAddressToSolochainAddress; + mapping(address => address) public validatorSolochainAddressToEthAddress; + + /// @inheritdoc IDataHavenServiceManager + address public validatorSetSubmitter; + + /// @inheritdoc IDataHavenServiceManager + mapping(IStrategy => uint96) public strategiesAndMultipliers; + /// @notice Storage gap for upgradeability (must be at end of state variables) // solhint-disable-next-line var-name-mixedcase - uint256[46] private __GAP; + uint256[43] private __GAP; // ============ Modifiers ============ @@ -88,6 +99,12 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave _; } + /// @notice Restricts function to the validator set submitter + modifier onlyValidatorSetSubmitter() { + _checkValidatorSetSubmitter(); + _; + } + function _checkRewardsInitiator() internal view { require(msg.sender == rewardsInitiator, OnlyRewardsInitiator()); } @@ -104,6 +121,10 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave require(msg.sender == address(_ALLOCATION_MANAGER), OnlyAllocationManager()); } + function _checkValidatorSetSubmitter() internal view { + require(msg.sender == validatorSetSubmitter, OnlyValidatorSetSubmitter()); + } + // ============ Constructor ============ /// @notice Sets the immutable EigenLayer contract references @@ -122,8 +143,9 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave function initialize( address initialOwner, address _rewardsInitiator, - IStrategy[] memory validatorsStrategies, - address _snowbridgeGatewayAddress + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory validatorsStrategiesAndMultipliers, + address _snowbridgeGatewayAddress, + address _validatorSetSubmitter ) public virtual initializer { require(initialOwner != address(0), ZeroAddress()); require(_rewardsInitiator != address(0), ZeroAddress()); @@ -137,51 +159,133 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave // Register the DataHaven service in the AllocationManager. _ALLOCATION_MANAGER.updateAVSMetadataURI(address(this), DATAHAVEN_AVS_METADATA); + // Build the strategies array and populate multipliers atomically so that + // getStrategiesInOperatorSet and strategiesAndMultipliers are always consistent. + IStrategy[] memory strategies = new IStrategy[](validatorsStrategiesAndMultipliers.length); + for (uint256 i = 0; i < validatorsStrategiesAndMultipliers.length; i++) { + strategies[i] = validatorsStrategiesAndMultipliers[i].strategy; + strategiesAndMultipliers[validatorsStrategiesAndMultipliers[i].strategy] = + validatorsStrategiesAndMultipliers[i].multiplier; + } + // Create the operator set for the DataHaven service. IAllocationManagerTypes.CreateSetParams[] memory operatorSets = new IAllocationManagerTypes.CreateSetParams[](1); operatorSets[0] = IAllocationManagerTypes.CreateSetParams({ - operatorSetId: VALIDATORS_SET_ID, strategies: validatorsStrategies + operatorSetId: VALIDATORS_SET_ID, strategies: strategies }); _ALLOCATION_MANAGER.createOperatorSets(address(this), operatorSets); // Set the Snowbridge Gateway address. _snowbridgeGateway = IGatewayV2(_snowbridgeGatewayAddress); + + // Set the validator set submitter if provided. + if (_validatorSetSubmitter != address(0)) { + validatorSetSubmitter = _validatorSetSubmitter; + emit ValidatorSetSubmitterUpdated(address(0), _validatorSetSubmitter); + } } /// @inheritdoc IDataHavenServiceManager - function sendNewValidatorSet( + function setValidatorSetSubmitter( + address newSubmitter + ) external onlyOwner { + require(newSubmitter != address(0), ZeroAddress()); + address oldSubmitter = validatorSetSubmitter; + validatorSetSubmitter = newSubmitter; + emit ValidatorSetSubmitterUpdated(oldSubmitter, newSubmitter); + } + + /// @inheritdoc IDataHavenServiceManager + function sendNewValidatorSetForEra( + uint64 targetEra, uint128 executionFee, uint128 relayerFee - ) external payable onlyOwner { - bytes memory message = buildNewValidatorSetMessage(); + ) external payable onlyValidatorSetSubmitter { + bytes memory message = buildNewValidatorSetMessageForEra(targetEra); _snowbridgeGateway.v2_sendMessage{value: msg.value}( message, new bytes[](0), bytes(""), executionFee, relayerFee ); + emit ValidatorSetMessageSubmitted(targetEra, keccak256(message), msg.sender); } /// @inheritdoc IDataHavenServiceManager - function buildNewValidatorSetMessage() public view returns (bytes memory) { + function buildNewValidatorSetMessageForEra( + uint64 targetEra + ) public view returns (bytes memory) { OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID}); - address[] memory currentValidatorSet = _ALLOCATION_MANAGER.getMembers(operatorSet); + address[] memory operators = _ALLOCATION_MANAGER.getMembers(operatorSet); + IStrategy[] memory strategies = _ALLOCATION_MANAGER.getStrategiesInOperatorSet(operatorSet); - // Allocate max size, then resize after filtering - address[] memory newValidatorSet = new address[](currentValidatorSet.length); - uint256 validCount = 0; - for (uint256 i = 0; i < currentValidatorSet.length; i++) { - address solochainAddr = validatorEthAddressToSolochainAddress[currentValidatorSet[i]]; - if (solochainAddr != address(0)) { - newValidatorSet[validCount] = solochainAddr; - ++validCount; + // Get allocated stake for all operators across all strategies + uint256[][] memory allocatedStake = + _ALLOCATION_MANAGER.getAllocatedStake(operatorSet, operators, strategies); + + // Collect candidates: operators with solochain mapping and non-zero weighted stake + address[] memory candidateSolochain = new address[](operators.length); + uint256[] memory candidateStake = new uint256[](operators.length); + address[] memory candidateOperator = new address[](operators.length); + uint256 candidateCount = 0; + + for (uint256 i = 0; i < operators.length; i++) { + address solochainAddr = validatorEthAddressToSolochainAddress[operators[i]]; + if (solochainAddr == address(0)) continue; + + // Compute weighted stake across all strategies: + // weightedStake = sum(allocatedStake[i][j] * multiplier[j]) + uint256 weightedStake = 0; + for (uint256 j = 0; j < strategies.length; j++) { + weightedStake += allocatedStake[i][j] + * uint256(strategiesAndMultipliers[strategies[j]]); + } + + if (weightedStake == 0) continue; + + candidateSolochain[candidateCount] = solochainAddr; + candidateStake[candidateCount] = weightedStake; + candidateOperator[candidateCount] = operators[i]; + candidateCount++; + } + + require(candidateCount != 0, EmptyValidatorSet()); + + // Partial selection sort: pick top min(MAX_ACTIVE_VALIDATORS, candidateCount) + uint256 selectCount = + candidateCount < MAX_ACTIVE_VALIDATORS ? candidateCount : MAX_ACTIVE_VALIDATORS; + + for (uint256 i = 0; i < selectCount; i++) { + uint256 bestIdx = i; + for (uint256 j = i + 1; j < candidateCount; j++) { + if (_isBetterCandidate( + candidateStake[j], + candidateOperator[j], + candidateStake[bestIdx], + candidateOperator[bestIdx] + )) { + bestIdx = j; + } + } + if (bestIdx != i) { + // Swap all parallel arrays + (candidateSolochain[i], candidateSolochain[bestIdx]) = + (candidateSolochain[bestIdx], candidateSolochain[i]); + (candidateStake[i], candidateStake[bestIdx]) = + (candidateStake[bestIdx], candidateStake[i]); + (candidateOperator[i], candidateOperator[bestIdx]) = + (candidateOperator[bestIdx], candidateOperator[i]); } } - // Resize array to actual count - assembly { - mstore(newValidatorSet, validCount) + + // Build the final validator set from sorted solochain addresses + address[] memory newValidatorSet = new address[](selectCount); + for (uint256 i = 0; i < selectCount; i++) { + newValidatorSet[i] = candidateSolochain[i]; } return DataHavenSnowbridgeMessages.scaleEncodeNewValidatorSetMessagePayload( - DataHavenSnowbridgeMessages.NewValidatorSetPayload({validators: newValidatorSet}) + DataHavenSnowbridgeMessages.NewValidatorSetPayload({ + validators: newValidatorSet, externalIndex: targetEra + }) ); } @@ -190,7 +294,20 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave address solochainAddress ) external onlyValidator { require(solochainAddress != address(0), ZeroAddress()); + + address existingEthOperator = validatorSolochainAddressToEthAddress[solochainAddress]; + require( + existingEthOperator == address(0) || existingEthOperator == msg.sender, + SolochainAddressAlreadyAssigned() + ); + + address oldSolochainAddress = validatorEthAddressToSolochainAddress[msg.sender]; + if (oldSolochainAddress != address(0) && oldSolochainAddress != solochainAddress) { + delete validatorSolochainAddressToEthAddress[oldSolochainAddress]; + } + validatorEthAddressToSolochainAddress[msg.sender] = solochainAddress; + validatorSolochainAddressToEthAddress[solochainAddress] = msg.sender; emit SolochainAddressUpdated(msg.sender, solochainAddress); } @@ -221,7 +338,21 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave require(operatorSetIds.length == 1, CantRegisterToMultipleOperatorSets()); require(operatorSetIds[0] == VALIDATORS_SET_ID, InvalidOperatorSetId()); require(validatorsAllowlist[operator], OperatorNotInAllowlist()); - validatorEthAddressToSolochainAddress[operator] = _toAddress(data); + + address solochainAddress = _toAddress(data); + address existingEthOperator = validatorSolochainAddressToEthAddress[solochainAddress]; + require( + existingEthOperator == address(0) || existingEthOperator == operator, + SolochainAddressAlreadyAssigned() + ); + + address oldSolochainAddress = validatorEthAddressToSolochainAddress[operator]; + if (oldSolochainAddress != address(0) && oldSolochainAddress != solochainAddress) { + delete validatorSolochainAddressToEthAddress[oldSolochainAddress]; + } + + validatorEthAddressToSolochainAddress[operator] = solochainAddress; + validatorSolochainAddressToEthAddress[solochainAddress] = operator; emit OperatorRegistered(operator, operatorSetIds[0]); } @@ -236,7 +367,11 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave require(operatorSetIds.length == 1, CantDeregisterFromMultipleOperatorSets()); require(operatorSetIds[0] == VALIDATORS_SET_ID, InvalidOperatorSetId()); + address oldSolochainAddress = validatorEthAddressToSolochainAddress[operator]; delete validatorEthAddressToSolochainAddress[operator]; + if (oldSolochainAddress != address(0)) { + delete validatorSolochainAddressToEthAddress[oldSolochainAddress]; + } emit OperatorDeregistered(operator, operatorSetIds[0]); } @@ -280,15 +415,71 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave _ALLOCATION_MANAGER.removeStrategiesFromOperatorSet( address(this), VALIDATORS_SET_ID, _strategies ); + + for (uint256 i = 0; i < _strategies.length; i++) { + delete strategiesAndMultipliers[_strategies[i]]; + } } /// @inheritdoc IDataHavenServiceManager function addStrategiesToValidatorsSupportedStrategies( - IStrategy[] calldata _strategies + IRewardsCoordinatorTypes.StrategyAndMultiplier[] calldata _strategyMultipliers ) external onlyOwner { - _ALLOCATION_MANAGER.addStrategiesToOperatorSet( - address(this), VALIDATORS_SET_ID, _strategies - ); + IStrategy[] memory strategies = new IStrategy[](_strategyMultipliers.length); + for (uint256 i = 0; i < _strategyMultipliers.length; i++) { + strategies[i] = _strategyMultipliers[i].strategy; + strategiesAndMultipliers[_strategyMultipliers[i].strategy] = + _strategyMultipliers[i].multiplier; + } + + _ALLOCATION_MANAGER.addStrategiesToOperatorSet(address(this), VALIDATORS_SET_ID, strategies); + + emit StrategiesAndMultipliersSet(_strategyMultipliers); + } + + /// @inheritdoc IDataHavenServiceManager + function setStrategiesAndMultipliers( + IRewardsCoordinatorTypes.StrategyAndMultiplier[] calldata _strategyMultipliers + ) external onlyOwner { + OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID}); + IStrategy[] memory registered = _ALLOCATION_MANAGER.getStrategiesInOperatorSet(operatorSet); + + for (uint256 i = 0; i < _strategyMultipliers.length; i++) { + bool found = false; + for (uint256 j = 0; j < registered.length; j++) { + if (registered[j] == _strategyMultipliers[i].strategy) { + found = true; + break; + } + } + require(found, StrategyNotInOperatorSet()); + + strategiesAndMultipliers[_strategyMultipliers[i].strategy] = + _strategyMultipliers[i].multiplier; + } + + emit StrategiesAndMultipliersSet(_strategyMultipliers); + } + + /// @inheritdoc IDataHavenServiceManager + function getStrategiesAndMultipliers() + external + view + returns (IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory) + { + OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID}); + IStrategy[] memory strategies = _ALLOCATION_MANAGER.getStrategiesInOperatorSet(operatorSet); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory result = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](strategies.length); + + for (uint256 i = 0; i < strategies.length; i++) { + result[i] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[i], multiplier: strategiesAndMultipliers[strategies[i]] + }); + } + + return result; } // ============ Rewards Functions ============ @@ -297,16 +488,22 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave function submitRewards( IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission calldata submission ) external override onlyRewardsInitiator { + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory translatedSubmission = + submission; uint256 totalAmount = 0; - for (uint256 i = 0; i < submission.operatorRewards.length; i++) { - totalAmount += submission.operatorRewards[i].amount; + for (uint256 i = 0; i < translatedSubmission.operatorRewards.length; i++) { + translatedSubmission.operatorRewards[i].operator = + _ethOperatorFromSolochain(translatedSubmission.operatorRewards[i].operator); + totalAmount += translatedSubmission.operatorRewards[i].amount; } + _sortOperatorRewards(translatedSubmission.operatorRewards); + submission.token.safeIncreaseAllowance(address(_REWARDS_COORDINATOR), totalAmount); IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] memory submissions = new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); - submissions[0] = submission; + submissions[0] = translatedSubmission; OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID}); _REWARDS_COORDINATOR.createOperatorDirectedOperatorSetRewardsSubmission( @@ -357,9 +554,10 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave SlashingRequest[] calldata slashings ) external onlyRewardsInitiator { for (uint256 i = 0; i < slashings.length; i++) { + address ethOperator = _ethOperatorFromSolochain(slashings[i].operator); IAllocationManagerTypes.SlashingParams memory slashingParams = IAllocationManagerTypes.SlashingParams({ - operator: slashings[i].operator, + operator: ethOperator, operatorSetId: VALIDATORS_SET_ID, strategies: slashings[i].strategies, wadsToSlash: slashings[i].wadsToSlash, @@ -374,6 +572,26 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave // ============ Internal Functions ============ + /** + * @notice Sorts operator rewards array by operator address in ascending order using insertion sort + * @dev Insertion sort is optimal for small arrays (validator set capped at 32) + * @param rewards The operator rewards array to sort in-place + */ + function _sortOperatorRewards( + IRewardsCoordinatorTypes.OperatorReward[] memory rewards + ) private pure { + uint256 len = rewards.length; + for (uint256 i = 1; i < len; i++) { + IRewardsCoordinatorTypes.OperatorReward memory key = rewards[i]; + uint256 j = i; + while (j > 0 && rewards[j - 1].operator > key.operator) { + rewards[j] = rewards[j - 1]; + j--; + } + rewards[j] = key; + } + } + /** * @notice Safely converts a 20-byte array to an address * @param data The bytes to convert (must be exactly 20 bytes) @@ -382,10 +600,43 @@ contract DataHavenServiceManager is OwnableUpgradeable, IAVSRegistrar, IDataHave function _toAddress( bytes memory data ) private pure returns (address result) { - require(data.length == 20, "Invalid address length"); + require(data.length == 20, InvalidSolochainAddressLength()); assembly { result := shr(96, mload(add(data, 32))) } require(result != address(0), ZeroAddress()); } + + /** + * @notice Determines if candidate A ranks higher than candidate B + * @dev Higher stake wins; on tie, lower operator address wins + * @param stakeA Weighted stake of candidate A + * @param opA Operator address of candidate A + * @param stakeB Weighted stake of candidate B + * @param opB Operator address of candidate B + * @return True if candidate A ranks higher than candidate B + */ + function _isBetterCandidate( + uint256 stakeA, + address opA, + uint256 stakeB, + address opB + ) private pure returns (bool) { + if (stakeA != stakeB) { + return stakeA > stakeB; + } + return opA < opB; + } + + /** + * @notice Returns the EigenLayer operator address for a Solochain validator address + * @dev Reverts if the Solochain address has not been mapped to an operator + */ + function _ethOperatorFromSolochain( + address solochainAddress + ) internal view returns (address) { + address ethOperator = validatorSolochainAddressToEthAddress[solochainAddress]; + require(ethOperator != address(0), UnknownSolochainAddress()); + return ethOperator; + } } diff --git a/contracts/src/interfaces/IDataHavenServiceManager.sol b/contracts/src/interfaces/IDataHavenServiceManager.sol index b1f40997..6782331b 100644 --- a/contracts/src/interfaces/IDataHavenServiceManager.sol +++ b/contracts/src/interfaces/IDataHavenServiceManager.sol @@ -32,6 +32,19 @@ interface IDataHavenServiceManagerErrors { error ZeroAddress(); /// @notice Thrown when the solochain address data length is not 20 bytes error InvalidSolochainAddressLength(); + /// @notice Thrown when the caller is not the authorized validator set submitter + error OnlyValidatorSetSubmitter(); + /// @notice Thrown when trying to submit a validator set message with zero validators + error EmptyValidatorSet(); + + /// @notice Thrown when a Solochain address has not been mapped to an EigenLayer operator + error UnknownSolochainAddress(); + + /// @notice Thrown when a Solochain address is already assigned to a different operator + error SolochainAddressAlreadyAssigned(); + + /// @notice Thrown when a strategy is not registered in the operator set + error StrategyNotInOperatorSet(); } /** @@ -78,6 +91,23 @@ interface IDataHavenServiceManagerEvents { /// @notice Emitted when a batch of slashing request is being successfully slashed event SlashingComplete(); + + /// @notice Emitted when strategy multipliers are set or updated + /// @param strategyMultipliers Array of strategy-multiplier pairs that were set + event StrategiesAndMultipliersSet(IRewardsCoordinatorTypes + .StrategyAndMultiplier[] strategyMultipliers); + /// @notice Emitted when the validator set submitter address is updated + /// @param oldSubmitter The previous validator set submitter address + /// @param newSubmitter The new validator set submitter address + event ValidatorSetSubmitterUpdated(address indexed oldSubmitter, address indexed newSubmitter); + + /// @notice Emitted when a validator set message is submitted for a target era + /// @param targetEra The target era for the validator set + /// @param payloadHash The keccak256 hash of the encoded message payload + /// @param submitter The address that submitted the validator set message + event ValidatorSetMessageSubmitted( + uint64 indexed targetEra, bytes32 payloadHash, address indexed submitter + ); } /** @@ -117,38 +147,73 @@ interface IDataHavenServiceManager is address validatorAddress ) external view returns (address); + /// @notice Returns the address authorized to submit validator set messages + /// @return The validator set submitter address + function validatorSetSubmitter() external view returns (address); + + /** + * @notice Sets the address authorized to submit validator set messages + * @param newSubmitter The new validator set submitter address + * @dev Only callable by the owner + */ + function setValidatorSetSubmitter( + address newSubmitter + ) external; + + /** + * @notice Converts a Solochain validator address to the corresponding EigenLayer operator address + * @param solochainAddress The Solochain validator address to convert + * @return The corresponding EigenLayer operator address + */ + function validatorSolochainAddressToEthAddress( + address solochainAddress + ) external view returns (address); + /** * @notice Initializes the DataHaven Service Manager * @param initialOwner Address of the initial owner * @param rewardsInitiator Address authorized to initiate rewards - * @param validatorsStrategies Array of strategies supported by validators + * @param validatorsStrategiesAndMultipliers Array of strategy-multiplier pairs for the validators + * operator set. Each multiplier must be non-zero. + * @param _snowbridgeGatewayAddress Address of the Snowbridge Gateway + * @param _validatorSetSubmitter Address authorized to submit validator set messages */ function initialize( address initialOwner, address rewardsInitiator, - IStrategy[] memory validatorsStrategies, - address _snowbridgeGatewayAddress + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory validatorsStrategiesAndMultipliers, + address _snowbridgeGatewayAddress, + address _validatorSetSubmitter ) external; /** - * @notice Sends a new validator set to the Snowbridge Gateway + * @notice Sends a new validator set for a target era to the Snowbridge Gateway * @dev The new validator set is made up of the Validators currently * registered in the DataHaven Service Manager as operators of * the Validators operator set (operatorSetId = VALIDATORS_SET_ID) - * @dev Only callable by the owner + * @dev Only callable by the validator set submitter + * @param targetEra The target era for the validator set submission * @param executionFee The execution fee for the Snowbridge message * @param relayerFee The relayer fee for the Snowbridge message */ - function sendNewValidatorSet( + function sendNewValidatorSetForEra( + uint64 targetEra, uint128 executionFee, uint128 relayerFee ) external payable; /** - * @notice Builds a new validator set message to be sent to the Snowbridge Gateway - * @return The encoded message bytes to be sent to the Snowbridge Gateway + * @notice Builds a SCALE-encoded message containing the top validators by weighted stake + * @dev Selects up to MAX_ACTIVE_VALIDATORS from registered operators. Each operator's + * weighted stake is computed as: sum(allocatedStake[j] * multiplier[j]) + * across all strategies. Operators without a solochain address mapping or with zero + * weighted stake are excluded. Ties are broken by lower operator address. + * @param targetEra The target era to encode in the message + * @return The SCALE-encoded message bytes to be sent to the Snowbridge Gateway */ - function buildNewValidatorSetMessage() external view returns (bytes memory); + function buildNewValidatorSetMessageForEra( + uint64 targetEra + ) external view returns (bytes memory); /** * @notice Updates the Solochain address for a Validator @@ -200,12 +265,50 @@ interface IDataHavenServiceManager is /** * @notice Adds strategies to the list of supported strategies for DataHaven Validators - * @param _strategies Array of strategy contracts to add to validators operator set + * @dev Each strategy's multiplier determines its weight in the validator selection + * formula: weightedStake = sum(allocatedStake[j] * multiplier[j]) + * @param _strategyMultipliers Array of strategy-multiplier pairs to add */ function addStrategiesToValidatorsSupportedStrategies( - IStrategy[] calldata _strategies + IRewardsCoordinatorTypes.StrategyAndMultiplier[] calldata _strategyMultipliers ) external; + /** + * @notice Returns the maximum number of active validators in the set + * @return The maximum active validators constant + */ + function MAX_ACTIVE_VALIDATORS() external pure returns (uint32); + + /** + * @notice Returns the multiplier for a given strategy + * @dev The multiplier determines how much an operator's allocated stake in this strategy + * contributes to their weighted stake during validator set selection. + * @param strategy The strategy to look up + * @return The multiplier weight + */ + function strategiesAndMultipliers( + IStrategy strategy + ) external view returns (uint96); + + /** + * @notice Updates multipliers for strategies already in the operator set + * @dev Does not add or remove strategies from EigenLayer; only updates multiplier weights + * used in the validator selection weighted stake formula + * @param _strategyMultipliers Array of strategy-multiplier pairs to update + */ + function setStrategiesAndMultipliers( + IRewardsCoordinatorTypes.StrategyAndMultiplier[] calldata _strategyMultipliers + ) external; + + /** + * @notice Returns all strategies with their multipliers + * @return Array of StrategyAndMultiplier structs with strategy addresses and multiplier weights + */ + function getStrategiesAndMultipliers() + external + view + returns (IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory); + // ============ Rewards Submitter Functions ============ /** diff --git a/contracts/src/libraries/DataHavenSnowbridgeMessages.sol b/contracts/src/libraries/DataHavenSnowbridgeMessages.sol index 3517eff1..e6ff132b 100644 --- a/contracts/src/libraries/DataHavenSnowbridgeMessages.sol +++ b/contracts/src/libraries/DataHavenSnowbridgeMessages.sol @@ -35,6 +35,8 @@ library DataHavenSnowbridgeMessages { struct NewValidatorSetPayload { /// @notice The list of validators in the DataHaven network. address[] validators; + /// @notice The external index (target era) for the validator set. + uint64 externalIndex; } /** @@ -48,8 +50,6 @@ library DataHavenSnowbridgeMessages { uint32 validatorsLen = uint32(payload.validators.length); address[] memory validatorSet = payload.validators; - uint64 externalIndex = uint64(0); - // Flatten the validator set into a single bytes array bytes memory validatorsFlattened; for (uint32 i = 0; i < validatorSet.length; i++) { @@ -63,7 +63,7 @@ library DataHavenSnowbridgeMessages { bytes1(uint8(OutboundCommandV1.ReceiveValidators)), ScaleCodec.encodeCompactU32(validatorsLen), validatorsFlattened, - ScaleCodec.encodeU64(externalIndex) + ScaleCodec.encodeU64(payload.externalIndex) ); } } diff --git a/contracts/storage-snapshots/DataHavenServiceManager.storage.json b/contracts/storage-snapshots/DataHavenServiceManager.storage.json new file mode 100644 index 00000000..9c49beeb --- /dev/null +++ b/contracts/storage-snapshots/DataHavenServiceManager.storage.json @@ -0,0 +1,184 @@ +{ + "storage": [ + { + "astId": 138, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 141, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 671, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 10, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 130, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 23775, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "rewardsInitiator", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 23780, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "validatorsAllowlist", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 23784, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_snowbridgeGateway", + "offset": 0, + "slot": "103", + "type": "t_contract(IGatewayV2)23481" + }, + { + "astId": 23789, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "validatorEthAddressToSolochainAddress", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 23793, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "validatorSolochainAddressToEthAddress", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 23796, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "validatorSetSubmitter", + "offset": 0, + "slot": "106", + "type": "t_address" + }, + { + "astId": 23802, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "strategiesAndMultipliers", + "offset": 0, + "slot": "107", + "type": "t_mapping(t_contract(IStrategy)7361,t_uint96)" + }, + { + "astId": 23807, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "__GAP", + "offset": 0, + "slot": "108", + "type": "t_array(t_uint256)43_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)43_storage": { + "encoding": "inplace", + "label": "uint256[43]", + "numberOfBytes": "1376", + "base": "t_uint256" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IGatewayV2)23481": { + "encoding": "inplace", + "label": "contract IGatewayV2", + "numberOfBytes": "20" + }, + "t_contract(IStrategy)7361": { + "encoding": "inplace", + "label": "contract IStrategy", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_contract(IStrategy)7361,t_uint96)": { + "encoding": "mapping", + "key": "t_contract(IStrategy)7361", + "label": "mapping(contract IStrategy => uint96)", + "numberOfBytes": "32", + "value": "t_uint96" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + }, + "t_uint96": { + "encoding": "inplace", + "label": "uint96", + "numberOfBytes": "12" + } + } +} diff --git a/contracts/storage-snapshots/README.md b/contracts/storage-snapshots/README.md new file mode 100644 index 00000000..bf708a11 --- /dev/null +++ b/contracts/storage-snapshots/README.md @@ -0,0 +1,75 @@ +# Storage Layout Snapshots + +This directory contains storage layout snapshots for upgradeable contracts. These snapshots are used to detect unintended storage layout changes that could corrupt state during proxy upgrades. + +## How It Works + +1. **Snapshot Comparison**: CI compares the current storage layout against committed snapshots +2. **Upgrade Simulation**: Foundry tests verify state preservation across upgrades + +## Updating Snapshots + +When you intentionally modify the storage layout of a contract (e.g., adding new state variables), you must update the snapshot: + +```bash +cd contracts +forge inspect DataHavenServiceManager storage --json > storage-snapshots/DataHavenServiceManager.storage.json +``` + +## Important Guidelines + +- **Never reorder existing variables** - This corrupts existing state +- **Never change types of existing variables** - This corrupts existing state +- **Always add new variables before the `__GAP`** - This preserves upgrade safety +- **Reduce gap size when adding variables** - Keep total slot count constant +- **Review snapshot diffs carefully** - Ensure changes are intentional + +## Current Contracts + +| Contract | Gap Size | Gap Slot | +|----------|----------|----------| +| DataHavenServiceManager | 46 | 105 | + +## Verification Commands + +```bash +# Check storage layout (CI script) +./scripts/check-storage-layout.sh + +# Negative check (proves detector fails on broken layout) +./scripts/check-storage-layout-negative.sh + +# Run upgrade simulation tests +forge test --match-contract StorageLayoutTest -vvv + +# View human-readable layout +forge inspect DataHavenServiceManager storage --pretty +``` + +## How Normalization Works + +The snapshot comparison normalizes both files to avoid false positives: + +- **Removes `astId`**: Changes with each compiler run +- **Removes `contract`**: Contains full file path +- **Removes `.types` section**: Contains unstable AST IDs that cause false diffs +- **Normalizes type IDs**: Strips unstable numeric suffixes from `type` (e.g., `t_contract(IGatewayV2)12345`) +- **Sorts by slot**: Ensures deterministic comparison + +This approach detects: +- Variable reordering or slot changes +- Top-level type changes (primitives, mappings, arrays) +- Gap size modifications + +## Note on Struct Storage + +If you add struct-typed storage variables in the future, be aware that **internal struct field changes may not be detected** by the snapshot diff. This is because: + +1. The `.types` section (which contains struct field definitions) is dropped to avoid unstable AST IDs +2. The storage slot assignment for a struct variable doesn't change when its internal fields change + +**However, this does not break upgrades** in the traditional sense. Struct field reordering or type changes within a struct would cause data misinterpretation (reading field A as field B), but the slot-level layout remains stable. + +**Mitigation**: If adding struct storage, ensure the upgrade simulation tests (`StorageLayoutTest`) explicitly verify struct field values survive upgrades. + +**Current status**: DataHavenServiceManager has no struct-typed storage variables, so this limitation does not apply. diff --git a/contracts/test/MessageEncoding.t.sol b/contracts/test/MessageEncoding.t.sol index 6b351835..d52fe108 100644 --- a/contracts/test/MessageEncoding.t.sol +++ b/contracts/test/MessageEncoding.t.sol @@ -15,7 +15,9 @@ contract MessageEncodingTest is Test { address[] memory mockValidators = TestUtils.generateMockValidatorsAddresses(3); DataHavenSnowbridgeMessages.NewValidatorSetPayload memory payload = - DataHavenSnowbridgeMessages.NewValidatorSetPayload({validators: mockValidators}); + DataHavenSnowbridgeMessages.NewValidatorSetPayload({ + validators: mockValidators, externalIndex: uint64(0) + }); bytes memory encodedMessage = DataHavenSnowbridgeMessages.scaleEncodeNewValidatorSetMessagePayload(payload); diff --git a/contracts/test/OperatorAddressMappings.t.sol b/contracts/test/OperatorAddressMappings.t.sol new file mode 100644 index 00000000..e49f9abd --- /dev/null +++ b/contracts/test/OperatorAddressMappings.t.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.27; + +import {AVSDeployer} from "./utils/AVSDeployer.sol"; +import {DataHavenServiceManager} from "../src/DataHavenServiceManager.sol"; +import { + IAllocationManagerTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {Test} from "forge-std/Test.sol"; + +contract OperatorAddressMappingsTest is AVSDeployer { + address public snowbridgeAgent = address(uint160(uint256(keccak256("snowbridgeAgent")))); + + address internal operator1 = address(uint160(uint256(keccak256("operator1")))); + address internal operator2 = address(uint160(uint256(keccak256("operator2")))); + + function setUp() public virtual { + _deployMockEigenLayerAndAVS(); + + // Configure the rewards initiator (not strictly needed for these tests, + // but keeps setup consistent with other suites). + vm.prank(avsOwner); + serviceManager.setRewardsInitiator(snowbridgeAgent); + } + + function _registerOperator( + address ethOperator, + address solochainOperator + ) internal { + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(ethOperator); + + vm.prank(ethOperator); + delegationManager.registerAsOperator(address(0), 0, ""); + + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = serviceManager.VALIDATORS_SET_ID(); + IAllocationManagerTypes.RegisterParams memory registerParams = + IAllocationManagerTypes.RegisterParams({ + avs: address(serviceManager), + operatorSetIds: operatorSetIds, + data: abi.encodePacked(solochainOperator) + }); + + vm.prank(ethOperator); + allocationManager.registerForOperatorSets(ethOperator, registerParams); + } + + function test_registerOperator_revertsIfSolochainAlreadyAssignedToDifferentOperator() public { + address sharedSolochain = address(0xBEEF); + + _registerOperator(operator1, sharedSolochain); + + // operator2 cannot claim the same solochain address + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(operator2); + vm.prank(operator2); + delegationManager.registerAsOperator(address(0), 0, ""); + + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = serviceManager.VALIDATORS_SET_ID(); + IAllocationManagerTypes.RegisterParams memory registerParams = + IAllocationManagerTypes.RegisterParams({ + avs: address(serviceManager), + operatorSetIds: operatorSetIds, + data: abi.encodePacked(sharedSolochain) + }); + + vm.prank(operator2); + vm.expectRevert(abi.encodeWithSignature("SolochainAddressAlreadyAssigned()")); + allocationManager.registerForOperatorSets(operator2, registerParams); + } + + function test_updateSolochainAddressForValidator_revertsIfAlreadyAssignedToDifferentOperator() + public + { + address solo1 = address(0xBEEF); + address solo2 = address(0xCAFE); + + _registerOperator(operator1, solo1); + _registerOperator(operator2, solo2); + + // operator2 cannot update to operator1's solochain address + vm.prank(operator2); + vm.expectRevert(abi.encodeWithSignature("SolochainAddressAlreadyAssigned()")); + serviceManager.updateSolochainAddressForValidator(solo1); + } + + function test_updateSolochainAddressForValidator_clearsOldReverseMapping() public { + address soloOld = address(0xBEEF); + address soloNew = address(0xCAFE); + + _registerOperator(operator1, soloOld); + + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(operator1), + soloOld, + "forward mapping should be set" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(soloOld), + operator1, + "reverse mapping should be set" + ); + + vm.prank(operator1); + serviceManager.updateSolochainAddressForValidator(soloNew); + + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(operator1), + soloNew, + "forward mapping should update" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(soloNew), + operator1, + "reverse mapping should update" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(soloOld), + address(0), + "old reverse mapping should be cleared" + ); + } + + function test_registerOperator_replacesSolochainAndClearsOldReverseMapping() public { + address soloOld = address(0xBEEF); + address soloNew = address(0xCAFE); + + _registerOperator(operator1, soloOld); + + // simulate allocationManager registering operator1 again with a new solochain address + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = serviceManager.VALIDATORS_SET_ID(); + + vm.prank(address(allocationManager)); + serviceManager.registerOperator( + operator1, address(serviceManager), operatorSetIds, abi.encodePacked(soloNew) + ); + + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(operator1), + soloNew, + "forward mapping should update" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(soloNew), + operator1, + "reverse mapping should update" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(soloOld), + address(0), + "old reverse mapping should be cleared" + ); + } +} + diff --git a/contracts/test/RewardsSubmitter.t.sol b/contracts/test/RewardsSubmitter.t.sol index 705ca575..8364296a 100644 --- a/contracts/test/RewardsSubmitter.t.sol +++ b/contracts/test/RewardsSubmitter.t.sol @@ -6,8 +6,13 @@ pragma solidity ^0.8.13; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { + IRewardsCoordinator, IRewardsCoordinatorTypes } from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; +import { + IAllocationManagerTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol"; import {AVSDeployer} from "./utils/AVSDeployer.sol"; import {ERC20FixedSupply} from "./utils/ERC20FixedSupply.sol"; @@ -41,6 +46,30 @@ contract RewardsSubmitterTest is AVSDeployer { IERC20(address(rewardToken)).safeTransfer(address(serviceManager), 100000e18); } + function _registerOperator( + address ethOperator, + address solochainOperator + ) internal { + // Allow our operator to register + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(ethOperator); + + vm.prank(ethOperator); + delegationManager.registerAsOperator(address(0), 0, ""); + + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = serviceManager.VALIDATORS_SET_ID(); + IAllocationManagerTypes.RegisterParams memory registerParams = + IAllocationManagerTypes.RegisterParams({ + avs: address(serviceManager), + operatorSetIds: operatorSetIds, + data: abi.encodePacked(solochainOperator) + }); + + vm.prank(ethOperator); + allocationManager.registerForOperatorSets(ethOperator, registerParams); + } + // Helper function to build a submission function _buildSubmission( uint256 rewardAmount, @@ -91,6 +120,7 @@ contract RewardsSubmitterTest is AVSDeployer { // ============ Access Control Tests ============ function test_submitRewards_revertsIfNotRewardsInitiator() public { + _registerOperator(operator1, operator1); IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory submission = _buildSubmission(1000e18, operator1); @@ -102,6 +132,7 @@ contract RewardsSubmitterTest is AVSDeployer { // ============ Success Tests ============ function test_submitRewards_singleOperator() public { + _registerOperator(operator1, operator1); uint256 rewardAmount = 1000e18; IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory submission = _buildSubmission(rewardAmount, operator1); @@ -116,6 +147,9 @@ contract RewardsSubmitterTest is AVSDeployer { } function test_submitRewards_multipleOperators() public { + _registerOperator(operator1, operator1); + _registerOperator(operator2, operator2); + // Build strategies IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory strategiesAndMultipliers = new IRewardsCoordinatorTypes.StrategyAndMultiplier[](deployedStrategies.length); @@ -126,8 +160,8 @@ contract RewardsSubmitterTest is AVSDeployer { } // Ensure operators are sorted in ascending order (required by EigenLayer) - address opLow = address(0x1); - address opHigh = address(0x2); + (address opLow, address opHigh) = + operator1 < operator2 ? (operator1, operator2) : (operator2, operator1); uint256 amount1 = 600e18; uint256 amount2 = 400e18; @@ -160,6 +194,7 @@ contract RewardsSubmitterTest is AVSDeployer { } function test_submitRewards_multipleSubmissions() public { + _registerOperator(operator1, operator1); uint32 duration = TEST_CALCULATION_INTERVAL; // Submit for period 0 @@ -188,6 +223,7 @@ contract RewardsSubmitterTest is AVSDeployer { } function test_submitRewards_withCustomDescription() public { + _registerOperator(operator1, operator1); // Build submission with custom description IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory strategiesAndMultipliers = new IRewardsCoordinatorTypes.StrategyAndMultiplier[](1); @@ -217,6 +253,7 @@ contract RewardsSubmitterTest is AVSDeployer { } function test_submitRewards_withDifferentToken() public { + _registerOperator(operator1, operator1); // Deploy a different token ERC20FixedSupply otherToken = new ERC20FixedSupply("Other", "OTHER", 1000000e18, address(this)); @@ -251,4 +288,153 @@ contract RewardsSubmitterTest is AVSDeployer { emit IDataHavenServiceManagerEvents.RewardsSubmitted(500e18, 1); serviceManager.submitRewards(submission); } + + function test_submitRewards_translatesSolochainOperatorToEthOperator() public { + address solochainOperator = address(0xBEEF); + _registerOperator(operator1, solochainOperator); + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(operator1), + solochainOperator, + "forward mapping should be set" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(solochainOperator), + operator1, + "reverse mapping should be set" + ); + + uint256 rewardAmount = 1000e18; + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory submission = + _buildSubmission(rewardAmount, solochainOperator); + + // Warp to a time after the period ends + vm.warp(submission.startTimestamp + submission.duration + 1); + + IRewardsCoordinatorTypes.OperatorReward[] memory expectedOperatorRewards = + new IRewardsCoordinatorTypes.OperatorReward[](1); + expectedOperatorRewards[0] = + IRewardsCoordinatorTypes.OperatorReward({operator: operator1, amount: rewardAmount}); + + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory expectedSubmission = + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + strategiesAndMultipliers: submission.strategiesAndMultipliers, + token: submission.token, + operatorRewards: expectedOperatorRewards, + startTimestamp: submission.startTimestamp, + duration: submission.duration, + description: submission.description + }); + + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] memory submissions = + new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); + submissions[0] = expectedSubmission; + + OperatorSet memory operatorSet = + OperatorSet({avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID()}); + vm.expectCall( + address(rewardsCoordinator), + abi.encodeCall( + IRewardsCoordinator.createOperatorDirectedOperatorSetRewardsSubmission, + (operatorSet, submissions) + ) + ); + + assertEq( + submission.operatorRewards[0].operator, + solochainOperator, + "submission should use solochain operator" + ); + vm.prank(snowbridgeAgent); + serviceManager.submitRewards(submission); + } + + function test_submitRewards_revertsIfUnknownSolochainAddress() public { + address unknownSolochainOperator = address(0xDEAD); + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory submission = + _buildSubmission(1000e18, unknownSolochainOperator); + + vm.prank(snowbridgeAgent); + vm.expectRevert(abi.encodeWithSignature("UnknownSolochainAddress()")); + serviceManager.submitRewards(submission); + } + + function test_submitRewards_sortsTranslatedOperatorsByAddress() public { + (address ethLow, address ethHigh) = + operator1 < operator2 ? (operator1, operator2) : (operator2, operator1); + + address solochainLow = address(0x1000); + address solochainHigh = address(0x2000); + + _registerOperator(ethLow, solochainHigh); + _registerOperator(ethHigh, solochainLow); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory strategiesAndMultipliers = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](deployedStrategies.length); + for (uint256 i = 0; i < deployedStrategies.length; i++) { + strategiesAndMultipliers[i] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: deployedStrategies[i], multiplier: uint96((i + 1) * 1e18) + }); + } + + uint256 amountForEthLow = 600e18; + uint256 amountForEthHigh = 400e18; + uint256 totalAmount = amountForEthLow + amountForEthHigh; + + IRewardsCoordinatorTypes.OperatorReward[] memory inputOperatorRewards = + new IRewardsCoordinatorTypes.OperatorReward[](2); + inputOperatorRewards[0] = IRewardsCoordinatorTypes.OperatorReward({ + operator: solochainLow, amount: amountForEthHigh + }); + inputOperatorRewards[1] = IRewardsCoordinatorTypes.OperatorReward({ + operator: solochainHigh, amount: amountForEthLow + }); + + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory submission = + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + strategiesAndMultipliers: strategiesAndMultipliers, + token: IERC20(address(rewardToken)), + operatorRewards: inputOperatorRewards, + startTimestamp: GENESIS_REWARDS_TIMESTAMP, + duration: TEST_CALCULATION_INTERVAL, + description: "DataHaven rewards" + }); + + vm.warp(submission.startTimestamp + submission.duration + 1); + + IRewardsCoordinatorTypes.OperatorReward[] memory expectedOperatorRewards = + new IRewardsCoordinatorTypes.OperatorReward[](2); + expectedOperatorRewards[0] = + IRewardsCoordinatorTypes.OperatorReward({operator: ethLow, amount: amountForEthLow}); + expectedOperatorRewards[1] = + IRewardsCoordinatorTypes.OperatorReward({operator: ethHigh, amount: amountForEthHigh}); + + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission memory expectedSubmission = + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission({ + strategiesAndMultipliers: strategiesAndMultipliers, + token: submission.token, + operatorRewards: expectedOperatorRewards, + startTimestamp: submission.startTimestamp, + duration: submission.duration, + description: submission.description + }); + + IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[] memory submissions = + new IRewardsCoordinatorTypes.OperatorDirectedRewardsSubmission[](1); + submissions[0] = expectedSubmission; + + OperatorSet memory operatorSet = + OperatorSet({avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID()}); + vm.expectCall( + address(rewardsCoordinator), + abi.encodeCall( + IRewardsCoordinator.createOperatorDirectedOperatorSetRewardsSubmission, + (operatorSet, submissions) + ) + ); + + vm.prank(snowbridgeAgent); + vm.expectEmit(false, false, false, true); + emit IDataHavenServiceManagerEvents.RewardsSubmitted(totalAmount, 2); + serviceManager.submitRewards(submission); + } } diff --git a/contracts/test/Slashing.t.sol b/contracts/test/Slashing.t.sol index 3e7c399e..8cac549a 100644 --- a/contracts/test/Slashing.t.sol +++ b/contracts/test/Slashing.t.sol @@ -26,6 +26,8 @@ contract SlashingTest is AVSDeployer { } function test_fulfilSlashingRequest() public { + address solochainOperator = address(0xBEEF); + // Allow our operator to register vm.prank(avsOwner); serviceManager.addValidatorToAllowlist(operator); @@ -43,7 +45,7 @@ contract SlashingTest is AVSDeployer { IAllocationManagerTypes.RegisterParams({ avs: address(serviceManager), operatorSetIds: operatorSetIds, - data: abi.encodePacked(address(operator)) + data: abi.encodePacked(solochainOperator) }); vm.prank(operator); @@ -61,7 +63,7 @@ contract SlashingTest is AVSDeployer { IStrategy[] memory strategies = allocationManager.getStrategiesInOperatorSet(operatorSet); slashings[0] = IDataHavenServiceManager.SlashingRequest( - operator, strategies, wadsToSlash, "Testing slashing" + solochainOperator, strategies, wadsToSlash, "Testing slashing" ); console.log(block.number); @@ -83,6 +85,8 @@ contract SlashingTest is AVSDeployer { } function test_fulfilSlashingRequestForOnlyOneStrategy() public { + address solochainOperator = address(0xBEEF); + // Allow our operator to register vm.prank(avsOwner); serviceManager.addValidatorToAllowlist(operator); @@ -100,7 +104,7 @@ contract SlashingTest is AVSDeployer { IAllocationManagerTypes.RegisterParams({ avs: address(serviceManager), operatorSetIds: operatorSetIds, - data: abi.encodePacked(address(operator)) + data: abi.encodePacked(solochainOperator) }); vm.prank(operator); @@ -119,7 +123,7 @@ contract SlashingTest is AVSDeployer { strategiesToSlash[0] = strategies[0]; slashings[0] = IDataHavenServiceManager.SlashingRequest( - operator, strategiesToSlash, wadsToSlash, "Testing slashing" + solochainOperator, strategiesToSlash, wadsToSlash, "Testing slashing" ); console.log(block.number); @@ -139,4 +143,24 @@ contract SlashingTest is AVSDeployer { emit IDataHavenServiceManagerEvents.SlashingComplete(); serviceManager.slashValidatorsOperator(slashings); } + + function test_fulfilSlashingRequest_revertsIfUnknownSolochainAddress() public { + // Configure the rewards initiator (because only the reward agent can submit slashing request) + vm.prank(avsOwner); + serviceManager.setRewardsInitiator(snowbridgeAgent); + + address unknownSolochainOperator = address(0xDEAD); + DataHavenServiceManager.SlashingRequest[] memory slashings = + new DataHavenServiceManager.SlashingRequest[](1); + slashings[0] = IDataHavenServiceManager.SlashingRequest( + unknownSolochainOperator, + new IStrategy[](0), + new uint256[](0), + "Testing unknown solochain operator" + ); + + vm.prank(snowbridgeAgent); + vm.expectRevert(abi.encodeWithSignature("UnknownSolochainAddress()")); + serviceManager.slashValidatorsOperator(slashings); + } } diff --git a/contracts/test/SnowbridgeIntegration.t.sol b/contracts/test/SnowbridgeIntegration.t.sol index d86bce53..f967553c 100644 --- a/contracts/test/SnowbridgeIntegration.t.sol +++ b/contracts/test/SnowbridgeIntegration.t.sol @@ -10,8 +10,13 @@ import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/Operator import {SnowbridgeAndAVSDeployer} from "./utils/SnowbridgeAndAVSDeployer.sol"; contract SnowbridgeIntegrationTest is SnowbridgeAndAVSDeployer { + address public submitter = address(uint160(uint256(keccak256("submitter")))); + function setUp() public { _deployMockAllContracts(); + // Set up the validator set submitter + vm.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitter); } function beforeTestSetup( @@ -19,7 +24,8 @@ contract SnowbridgeIntegrationTest is SnowbridgeAndAVSDeployer { ) public pure returns (bytes[] memory beforeTestCalldata) { if (testSelector == this.test_sendNewValidatorsSetMessage.selector) { beforeTestCalldata = new bytes[](1); - beforeTestCalldata[0] = abi.encodeWithSelector(this.setupValidatorsAsOperators.selector); + beforeTestCalldata[0] = + abi.encodeWithSelector(this.setupValidatorsAsOperatorsWithAllocations.selector); } } @@ -36,11 +42,13 @@ contract SnowbridgeIntegrationTest is SnowbridgeAndAVSDeployer { ); } - // Mock balance for the AVS owner - vm.deal(avsOwner, 1000000 ether); + uint64 targetEra = 42; + + // Mock balance for the submitter + vm.deal(submitter, 1000000 ether); // Send the new validator set message to the Snowbridge Gateway - bytes memory message = serviceManager.buildNewValidatorSetMessage(); + bytes memory message = serviceManager.buildNewValidatorSetMessageForEra(targetEra); Payload memory payload = Payload({ origin: address(serviceManager), assets: new Asset[](0), @@ -52,7 +60,7 @@ contract SnowbridgeIntegrationTest is SnowbridgeAndAVSDeployer { }); cheats.expectEmit(); emit IGatewayV2.OutboundMessageAccepted(1, payload); - cheats.prank(avsOwner); - serviceManager.sendNewValidatorSet{value: 2 ether}(1 ether, 1 ether); + cheats.prank(submitter); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(targetEra, 1 ether, 1 ether); } } diff --git a/contracts/test/ValidatorSetSelection.t.sol b/contracts/test/ValidatorSetSelection.t.sol new file mode 100644 index 00000000..d58be58c --- /dev/null +++ b/contracts/test/ValidatorSetSelection.t.sol @@ -0,0 +1,568 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.27; + +/* solhint-disable func-name-mixedcase */ + +import {SnowbridgeAndAVSDeployer} from "./utils/SnowbridgeAndAVSDeployer.sol"; +import {DataHavenSnowbridgeMessages} from "../src/libraries/DataHavenSnowbridgeMessages.sol"; +import {IDataHavenServiceManagerErrors} from "../src/interfaces/IDataHavenServiceManager.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import { + IRewardsCoordinatorTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; +import { + IAllocationManagerTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ValidatorSetSelectionTest is SnowbridgeAndAVSDeployer { + function setUp() public { + _deployMockAllContracts(); + } + + // ============ Helpers ============ + + function _getStrategies() internal view returns (IStrategy[] memory) { + IStrategy[] memory strategies = new IStrategy[](deployedStrategies.length); + for (uint256 i = 0; i < deployedStrategies.length; i++) { + strategies[i] = deployedStrategies[i]; + } + return strategies; + } + + function _setupMultipliers( + uint96[] memory multipliers + ) internal { + IStrategy[] memory strategies = _getStrategies(); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](strategies.length); + for (uint256 i = 0; i < strategies.length; i++) { + sm[i] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[i], multiplier: multipliers[i] + }); + } + + cheats.startPrank(avsOwner); + serviceManager.removeStrategiesFromValidatorsSupportedStrategies(strategies); + serviceManager.addStrategiesToValidatorsSupportedStrategies(sm); + cheats.stopPrank(); + } + + function _uniformMultipliers() internal pure returns (uint96[] memory) { + uint96[] memory m = new uint96[](3); + m[0] = 1; + m[1] = 1; + m[2] = 1; + return m; + } + + function _registerOperator( + address op, + address solochainAddr, + uint256[] memory stakeAmounts + ) internal { + cheats.prank(avsOwner); + serviceManager.addValidatorToAllowlist(op); + + cheats.startPrank(op); + for (uint256 j = 0; j < deployedStrategies.length; j++) { + IERC20 linkedToken = deployedStrategies[j].underlyingToken(); + _setERC20Balance(address(linkedToken), op, stakeAmounts[j]); + linkedToken.approve(address(strategyManager), stakeAmounts[j]); + strategyManager.depositIntoStrategy(deployedStrategies[j], linkedToken, stakeAmounts[j]); + } + delegationManager.registerAsOperator(address(0), 0, ""); + + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = serviceManager.VALIDATORS_SET_ID(); + IAllocationManagerTypes.RegisterParams memory registerParams = + IAllocationManagerTypes.RegisterParams({ + avs: address(serviceManager), + operatorSetIds: operatorSetIds, + data: abi.encodePacked(solochainAddr) + }); + allocationManager.registerForOperatorSets(op, registerParams); + cheats.stopPrank(); + } + + function _uniformStakes( + uint256 amount + ) internal view returns (uint256[] memory) { + uint256[] memory stakes = new uint256[](deployedStrategies.length); + for (uint256 j = 0; j < stakes.length; j++) { + stakes[j] = amount; + } + return stakes; + } + + function _allocateForOperator( + address op + ) internal { + IStrategy[] memory strategies = _getStrategies(); + uint64[] memory newMagnitudes = new uint64[](strategies.length); + for (uint256 j = 0; j < strategies.length; j++) { + newMagnitudes[j] = 1e18; + } + + IAllocationManagerTypes.AllocateParams[] memory allocParams = + new IAllocationManagerTypes.AllocateParams[](1); + allocParams[0] = IAllocationManagerTypes.AllocateParams({ + operatorSet: OperatorSet({ + avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID() + }), + strategies: strategies, + newMagnitudes: newMagnitudes + }); + + cheats.prank(op); + allocationManager.modifyAllocations(op, allocParams); + } + + function _advancePastAllocationConfigDelay() internal { + uint32 delay = allocationManager.ALLOCATION_CONFIGURATION_DELAY(); + cheats.roll(block.number + delay + 1); + } + + function _advancePastAllocationEffect() internal { + cheats.roll(block.number + 1); + } + + function _buildExpectedMessage( + address[] memory validators, + uint64 externalIndex + ) internal pure returns (bytes memory) { + return DataHavenSnowbridgeMessages.scaleEncodeNewValidatorSetMessagePayload( + DataHavenSnowbridgeMessages.NewValidatorSetPayload({ + validators: validators, externalIndex: externalIndex + }) + ); + } + + // ============ Admin Function Tests ============ + + // Test #7: Add strategy + multiplier in one call; verify both stored + function test_addStrategies_setsMultiplierAtomically() public { + IStrategy[] memory strategies = _getStrategies(); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](3); + sm[0] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[0], multiplier: 5000 + }); + sm[1] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[1], multiplier: 10000 + }); + sm[2] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[2], multiplier: 2000 + }); + + cheats.startPrank(avsOwner); + serviceManager.removeStrategiesFromValidatorsSupportedStrategies(strategies); + serviceManager.addStrategiesToValidatorsSupportedStrategies(sm); + cheats.stopPrank(); + + assertEq(serviceManager.strategiesAndMultipliers(strategies[0]), 5000); + assertEq(serviceManager.strategiesAndMultipliers(strategies[1]), 10000); + assertEq(serviceManager.strategiesAndMultipliers(strategies[2]), 2000); + } + + // Test #9: Remove strategy → multiplier and tracking bool deleted + function test_removeStrategies_cleansUpMultiplier() public { + IStrategy[] memory strategies = _getStrategies(); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](3); + sm[0] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[0], multiplier: 5000 + }); + sm[1] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[1], multiplier: 10000 + }); + sm[2] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[2], multiplier: 2000 + }); + + cheats.startPrank(avsOwner); + serviceManager.removeStrategiesFromValidatorsSupportedStrategies(strategies); + serviceManager.addStrategiesToValidatorsSupportedStrategies(sm); + + assertEq(serviceManager.strategiesAndMultipliers(strategies[1]), 10000); + + serviceManager.removeStrategiesFromValidatorsSupportedStrategies(strategies); + cheats.stopPrank(); + + assertEq(serviceManager.strategiesAndMultipliers(strategies[0]), 0); + assertEq(serviceManager.strategiesAndMultipliers(strategies[1]), 0); + assertEq(serviceManager.strategiesAndMultipliers(strategies[2]), 0); + } + + // Test #11: Returns correct StrategyAndMultiplier structs + function test_getStrategiesAndMultipliers_returnsCorrect() public { + IStrategy[] memory strategies = _getStrategies(); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](3); + sm[0] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[0], multiplier: 5000 + }); + sm[1] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[1], multiplier: 10000 + }); + sm[2] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[2], multiplier: 2000 + }); + + cheats.startPrank(avsOwner); + serviceManager.removeStrategiesFromValidatorsSupportedStrategies(strategies); + serviceManager.addStrategiesToValidatorsSupportedStrategies(sm); + cheats.stopPrank(); + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory result = + serviceManager.getStrategiesAndMultipliers(); + + assertEq(result.length, 3); + for (uint256 i = 0; i < result.length; i++) { + uint96 expectedMultiplier = serviceManager.strategiesAndMultipliers(result[i].strategy); + assertEq(result[i].multiplier, expectedMultiplier); + } + } + + // Test: setStrategiesAndMultipliers updates existing multipliers + function test_setStrategiesAndMultipliers_updatesMultipliers() public { + IStrategy[] memory strategies = _getStrategies(); + + // Set initial multipliers via _setupMultipliers + uint96[] memory initial = new uint96[](3); + initial[0] = 5000; + initial[1] = 10000; + initial[2] = 2000; + _setupMultipliers(initial); + + // Update multipliers + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory updated = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](3); + updated[0] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[0], multiplier: 1 + }); + updated[1] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[1], multiplier: 1 + }); + updated[2] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[2], multiplier: 9999 + }); + + cheats.prank(avsOwner); + serviceManager.setStrategiesAndMultipliers(updated); + + assertEq(serviceManager.strategiesAndMultipliers(strategies[0]), 1); + assertEq(serviceManager.strategiesAndMultipliers(strategies[1]), 1); + assertEq(serviceManager.strategiesAndMultipliers(strategies[2]), 9999); + } + + // Test: setStrategiesAndMultipliers changes validator ranking + function test_setStrategiesAndMultipliers_affectsRanking() public { + uint96[] memory mults = new uint96[](3); + mults[0] = 10000; + mults[1] = 1; + mults[2] = 1; + _setupMultipliers(mults); + + // Op A: heavy in strategy 0 (high multiplier) → initially ranked first + address opA = vm.addr(801); + address solochainA = address(uint160(0x6001)); + uint256[] memory stakesA = new uint256[](3); + stakesA[0] = 1000 ether; + stakesA[1] = 10 ether; + stakesA[2] = 10 ether; + _registerOperator(opA, solochainA, stakesA); + + // Op B: heavy in strategy 1 (low multiplier) → initially ranked second + address opB = vm.addr(802); + address solochainB = address(uint160(0x6002)); + uint256[] memory stakesB = new uint256[](3); + stakesB[0] = 10 ether; + stakesB[1] = 1000 ether; + stakesB[2] = 10 ether; + _registerOperator(opB, solochainB, stakesB); + + _advancePastAllocationConfigDelay(); + _allocateForOperator(opA); + _allocateForOperator(opB); + _advancePastAllocationEffect(); + + // Before update: A ranks first (strategy 0 has multiplier 10_000) + address[] memory expectedBefore = new address[](2); + expectedBefore[0] = solochainA; + expectedBefore[1] = solochainB; + assertEq( + serviceManager.buildNewValidatorSetMessageForEra(0), + _buildExpectedMessage(expectedBefore, 0) + ); + + // Flip multipliers: strategy 1 now has high multiplier + IStrategy[] memory strategies = _getStrategies(); + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory flipped = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](3); + flipped[0] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[0], multiplier: 1 + }); + flipped[1] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[1], multiplier: 10000 + }); + flipped[2] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[2], multiplier: 1 + }); + + cheats.prank(avsOwner); + serviceManager.setStrategiesAndMultipliers(flipped); + + // After update: B ranks first (strategy 1 now has multiplier 10_000) + address[] memory expectedAfter = new address[](2); + expectedAfter[0] = solochainB; + expectedAfter[1] = solochainA; + assertEq( + serviceManager.buildNewValidatorSetMessageForEra(0), + _buildExpectedMessage(expectedAfter, 0) + ); + } + + // ============ Selection Tests ============ + + // Test #1: 3 strategies with different multipliers; verify correct ordering + function test_weightedStake_multipleStrategies() public { + uint96[] memory mults = new uint96[](3); + mults[0] = 5000; + mults[1] = 10000; + mults[2] = 2000; + _setupMultipliers(mults); + + // Op A: heavy in strategy 0 (multiplier 5000) + address opA = vm.addr(101); + address solochainA = address(uint160(0xA01)); + uint256[] memory stakesA = new uint256[](3); + stakesA[0] = 1000 ether; + stakesA[1] = 100 ether; + stakesA[2] = 100 ether; + _registerOperator(opA, solochainA, stakesA); + + // Op B: heavy in strategy 1 (multiplier 10000) → highest weighted stake + address opB = vm.addr(102); + address solochainB = address(uint160(0xB01)); + uint256[] memory stakesB = new uint256[](3); + stakesB[0] = 100 ether; + stakesB[1] = 1000 ether; + stakesB[2] = 100 ether; + _registerOperator(opB, solochainB, stakesB); + + // Op C: heavy in strategy 2 (multiplier 2000) → lowest weighted stake + address opC = vm.addr(103); + address solochainC = address(uint160(0xC01)); + uint256[] memory stakesC = new uint256[](3); + stakesC[0] = 100 ether; + stakesC[1] = 100 ether; + stakesC[2] = 1000 ether; + _registerOperator(opC, solochainC, stakesC); + + _advancePastAllocationConfigDelay(); + + _allocateForOperator(opA); + _allocateForOperator(opB); + _allocateForOperator(opC); + + _advancePastAllocationEffect(); + + // Expected order: B (highest multiplied strategy), A, C + address[] memory expected = new address[](3); + expected[0] = solochainB; + expected[1] = solochainA; + expected[2] = solochainC; + + assertEq( + serviceManager.buildNewValidatorSetMessageForEra(0), _buildExpectedMessage(expected, 0) + ); + } + + // Test #2: 2 operators with identical weighted stake; lower Eth address ranks first + function test_tieBreak_lowerAddressWins() public { + _setupMultipliers(_uniformMultipliers()); + + address addrA = vm.addr(201); + address addrB = vm.addr(202); + + // Ensure addrLow < addrHigh + address addrLow = addrA < addrB ? addrA : addrB; + address addrHigh = addrA < addrB ? addrB : addrA; + + address solochainLow = address(uint160(0xBB)); + address solochainHigh = address(uint160(0xAA)); + + _registerOperator(addrLow, solochainLow, _uniformStakes(500 ether)); + _registerOperator(addrHigh, solochainHigh, _uniformStakes(500 ether)); + + _advancePastAllocationConfigDelay(); + + _allocateForOperator(addrLow); + _allocateForOperator(addrHigh); + + _advancePastAllocationEffect(); + + // Lower Eth address wins tie-break + address[] memory expected = new address[](2); + expected[0] = solochainLow; + expected[1] = solochainHigh; + + assertEq( + serviceManager.buildNewValidatorSetMessageForEra(0), _buildExpectedMessage(expected, 0) + ); + } + + // Test #3: Register 35 operators; verify only top 32 selected + function test_topN_moreThan32() public { + _setupMultipliers(_uniformMultipliers()); + + uint256 totalOps = 35; + address[] memory operators = new address[](totalOps); + address[] memory solochainAddrs = new address[](totalOps); + + for (uint256 i = 0; i < totalOps; i++) { + operators[i] = vm.addr(300 + i); + solochainAddrs[i] = address(uint160(0x1000 + i)); + _registerOperator(operators[i], solochainAddrs[i], _uniformStakes((i + 1) * 10 ether)); + } + + _advancePastAllocationConfigDelay(); + + for (uint256 i = 0; i < totalOps; i++) { + _allocateForOperator(operators[i]); + } + + _advancePastAllocationEffect(); + + bytes memory message = serviceManager.buildNewValidatorSetMessageForEra(0); + + // Top 32 by descending stake: operators at indices 34, 33, ..., 3 + address[] memory expected = new address[](32); + for (uint256 i = 0; i < 32; i++) { + expected[i] = solochainAddrs[totalOps - 1 - i]; + } + + assertEq(message, _buildExpectedMessage(expected, 0)); + } + + // Test #4: 5 operators; all included in output + function test_lessThan32_includesAll() public { + _setupMultipliers(_uniformMultipliers()); + + uint256 totalOps = 5; + address[] memory operators = new address[](totalOps); + address[] memory solochainAddrs = new address[](totalOps); + + for (uint256 i = 0; i < totalOps; i++) { + operators[i] = vm.addr(400 + i); + solochainAddrs[i] = address(uint160(0x2000 + i)); + _registerOperator(operators[i], solochainAddrs[i], _uniformStakes((i + 1) * 100 ether)); + } + + _advancePastAllocationConfigDelay(); + + for (uint256 i = 0; i < totalOps; i++) { + _allocateForOperator(operators[i]); + } + + _advancePastAllocationEffect(); + + // All 5 included, sorted by descending stake + address[] memory expected = new address[](5); + for (uint256 i = 0; i < 5; i++) { + expected[i] = solochainAddrs[totalOps - 1 - i]; + } + + assertEq( + serviceManager.buildNewValidatorSetMessageForEra(0), _buildExpectedMessage(expected, 0) + ); + } + + // Test #5: Operator with zero allocation excluded + function test_zeroWeightedStake_filtered() public { + _setupMultipliers(_uniformMultipliers()); + + address op1 = vm.addr(501); + address solochain1 = address(uint160(0x3001)); + _registerOperator(op1, solochain1, _uniformStakes(100 ether)); + + address op2 = vm.addr(502); + address solochain2 = address(uint160(0x3002)); + _registerOperator(op2, solochain2, _uniformStakes(200 ether)); + + // op3 registered but NOT allocated → zero weighted stake + address op3 = vm.addr(503); + address solochain3 = address(uint160(0x3003)); + _registerOperator(op3, solochain3, _uniformStakes(300 ether)); + + _advancePastAllocationConfigDelay(); + + // Only allocate for op1 and op2 + _allocateForOperator(op1); + _allocateForOperator(op2); + + _advancePastAllocationEffect(); + + // op3 should be filtered out + address[] memory expected = new address[](2); + expected[0] = solochain2; + expected[1] = solochain1; + + assertEq( + serviceManager.buildNewValidatorSetMessageForEra(0), _buildExpectedMessage(expected, 0) + ); + } + + // Test #6: A zero multiplier is accepted and causes that strategy's stake to contribute + // no weight. The operator is still included if other strategies have non-zero multipliers. + function test_zeroMultiplier_accepted_contributesNoWeight() public { + IStrategy[] memory strategies = _getStrategies(); + + // Zero-out the first strategy's multiplier via setStrategiesAndMultipliers + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](1); + sm[0] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[0], multiplier: 0 + }); + + cheats.prank(avsOwner); + serviceManager.setStrategiesAndMultipliers(sm); + + assertEq(serviceManager.strategiesAndMultipliers(strategies[0]), 0); + } + + // Test #12: Full integration — weighted selection + correct message encoding + function test_buildMessage_encodesCorrectly() public { + _setupMultipliers(_uniformMultipliers()); + + address op1 = vm.addr(701); + address solochain1 = address(uint160(0x5001)); + _registerOperator(op1, solochain1, _uniformStakes(500 ether)); + + address op2 = vm.addr(702); + address solochain2 = address(uint160(0x5002)); + _registerOperator(op2, solochain2, _uniformStakes(1000 ether)); + + _advancePastAllocationConfigDelay(); + + _allocateForOperator(op1); + _allocateForOperator(op2); + + _advancePastAllocationEffect(); + + bytes memory message = serviceManager.buildNewValidatorSetMessageForEra(0); + + // op2 has higher stake → first + address[] memory expected = new address[](2); + expected[0] = solochain2; + expected[1] = solochain1; + + assertEq(message, _buildExpectedMessage(expected, 0)); + } +} diff --git a/contracts/test/ValidatorSetSubmitter.t.sol b/contracts/test/ValidatorSetSubmitter.t.sol new file mode 100644 index 00000000..ab6cdef7 --- /dev/null +++ b/contracts/test/ValidatorSetSubmitter.t.sol @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +/* solhint-disable func-name-mixedcase */ + +import {SnowbridgeAndAVSDeployer} from "./utils/SnowbridgeAndAVSDeployer.sol"; +import { + IDataHavenServiceManagerErrors, + IDataHavenServiceManagerEvents +} from "../src/interfaces/IDataHavenServiceManager.sol"; +import {DataHavenServiceManager} from "../src/DataHavenServiceManager.sol"; +import { + TransparentUpgradeableProxy +} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { + IRewardsCoordinatorTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; + +contract ValidatorSetSubmitterTest is SnowbridgeAndAVSDeployer { + address public submitterA = address(uint160(uint256(keccak256("submitterA")))); + address public submitterB = address(uint160(uint256(keccak256("submitterB")))); + address public nonOwner = address(uint160(uint256(keccak256("nonOwner")))); + + function setUp() public { + _deployMockAllContracts(); + } + + function beforeTestSetup( + bytes4 testSelector + ) public pure returns (bytes[] memory beforeTestCalldata) { + if ( + testSelector == this.test_sendNewValidatorSetForEra_success.selector + || testSelector + == this.test_buildNewValidatorSetMessageForEra_encodesTargetEra.selector + || testSelector == this.test_fuzz_sendNewValidatorSetForEra.selector + || testSelector + == this.test_buildNewValidatorSetMessageForEra_exactEncoding.selector + ) { + beforeTestCalldata = new bytes[](1); + beforeTestCalldata[0] = + abi.encodeWithSelector(this.setupValidatorsAsOperatorsWithAllocations.selector); + } + } + + // ============ setValidatorSetSubmitter ============ + + function test_setValidatorSetSubmitter() public { + // After initialization, validatorSetSubmitter is already set to avsOwner + assertEq( + serviceManager.validatorSetSubmitter(), + avsOwner, + "validatorSetSubmitter should be set to avsOwner after init" + ); + + cheats.expectEmit(); + emit IDataHavenServiceManagerEvents.ValidatorSetSubmitterUpdated(avsOwner, submitterA); + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + + assertEq( + serviceManager.validatorSetSubmitter(), + submitterA, + "validatorSetSubmitter should be set" + ); + } + + function test_setValidatorSetSubmitter_revertsIfNotOwner() public { + cheats.prank(nonOwner); + cheats.expectRevert(); + serviceManager.setValidatorSetSubmitter(submitterA); + } + + function test_setValidatorSetSubmitter_revertsOnZeroAddress() public { + cheats.prank(avsOwner); + cheats.expectRevert( + abi.encodeWithSelector(IDataHavenServiceManagerErrors.ZeroAddress.selector) + ); + serviceManager.setValidatorSetSubmitter(address(0)); + } + + function test_setValidatorSetSubmitter_rotation() public { + // Set submitter A (rotating from avsOwner set during init) + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + assertEq(serviceManager.validatorSetSubmitter(), submitterA); + + // Rotate to submitter B + cheats.expectEmit(); + emit IDataHavenServiceManagerEvents.ValidatorSetSubmitterUpdated(submitterA, submitterB); + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterB); + assertEq(serviceManager.validatorSetSubmitter(), submitterB); + + // Old submitter A can no longer submit + vm.deal(submitterA, 10 ether); + cheats.prank(submitterA); + cheats.expectRevert( + abi.encodeWithSelector( + IDataHavenServiceManagerErrors.OnlyValidatorSetSubmitter.selector + ) + ); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(1, 1 ether, 1 ether); + } + + // ============ sendNewValidatorSetForEra ============ + + function test_sendNewValidatorSetForEra_revertsIfNotSubmitter() public { + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + + vm.deal(nonOwner, 10 ether); + cheats.prank(nonOwner); + cheats.expectRevert( + abi.encodeWithSelector( + IDataHavenServiceManagerErrors.OnlyValidatorSetSubmitter.selector + ) + ); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(1, 1 ether, 1 ether); + } + + function test_sendNewValidatorSetForEra_success() public { + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + + uint64 targetEra = 42; + vm.deal(submitterA, 1000000 ether); + + bytes memory message = serviceManager.buildNewValidatorSetMessageForEra(targetEra); + bytes32 expectedHash = keccak256(message); + + cheats.expectEmit(); + emit IDataHavenServiceManagerEvents.ValidatorSetMessageSubmitted( + targetEra, expectedHash, submitterA + ); + cheats.prank(submitterA); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(targetEra, 1 ether, 1 ether); + } + + function test_sendNewValidatorSetForEra_revertsOnEmptyValidatorSet() public { + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + + vm.deal(submitterA, 10 ether); + cheats.prank(submitterA); + cheats.expectRevert( + abi.encodeWithSelector(IDataHavenServiceManagerErrors.EmptyValidatorSet.selector) + ); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(1, 1 ether, 1 ether); + } + + function test_ownerCannotCallSendNewValidatorSetForEra() public { + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + + vm.deal(avsOwner, 10 ether); + cheats.prank(avsOwner); + cheats.expectRevert( + abi.encodeWithSelector( + IDataHavenServiceManagerErrors.OnlyValidatorSetSubmitter.selector + ) + ); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(1, 1 ether, 1 ether); + } + + // ============ buildNewValidatorSetMessageForEra ============ + + function test_buildNewValidatorSetMessageForEra_encodesTargetEra() public view { + bytes memory messageEra1 = serviceManager.buildNewValidatorSetMessageForEra(1); + bytes memory messageEra2 = serviceManager.buildNewValidatorSetMessageForEra(2); + bytes memory messageEra100 = serviceManager.buildNewValidatorSetMessageForEra(100); + + // Different era values must produce different encoded output + assertTrue( + keccak256(messageEra1) != keccak256(messageEra2), + "Messages for different eras should differ" + ); + assertTrue( + keccak256(messageEra1) != keccak256(messageEra100), + "Messages for different eras should differ" + ); + } + + function test_sendNewValidatorSetForEra_revertsWhenSubmitterIsZeroAddress() public { + // Deploy a fresh proxy with address(0) as the submitter + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory emptyStrategies = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](0); + + cheats.startPrank(regularDeployer); + DataHavenServiceManager zeroSubmitterSM = DataHavenServiceManager( + address( + new TransparentUpgradeableProxy( + address(serviceManagerImplementation), + address(proxyAdmin), + abi.encodeWithSelector( + DataHavenServiceManager.initialize.selector, + avsOwner, + rewardsInitiator, + emptyStrategies, + address(snowbridgeGatewayMock), + address(0) + ) + ) + ) + ); + cheats.stopPrank(); + + assertEq( + zeroSubmitterSM.validatorSetSubmitter(), + address(0), + "validatorSetSubmitter should be address(0)" + ); + + vm.deal(submitterA, 10 ether); + cheats.prank(submitterA); + cheats.expectRevert( + abi.encodeWithSelector( + IDataHavenServiceManagerErrors.OnlyValidatorSetSubmitter.selector + ) + ); + zeroSubmitterSM.sendNewValidatorSetForEra{value: 2 ether}(1, 1 ether, 1 ether); + } + + function test_fuzz_sendNewValidatorSetForEra( + uint64 targetEra + ) public { + cheats.prank(avsOwner); + serviceManager.setValidatorSetSubmitter(submitterA); + + vm.deal(submitterA, 1000000 ether); + + bytes memory message = serviceManager.buildNewValidatorSetMessageForEra(targetEra); + bytes32 expectedHash = keccak256(message); + + cheats.expectEmit(); + emit IDataHavenServiceManagerEvents.ValidatorSetMessageSubmitted( + targetEra, expectedHash, submitterA + ); + cheats.prank(submitterA); + serviceManager.sendNewValidatorSetForEra{value: 2 ether}(targetEra, 1 ether, 1 ether); + } + + function test_buildNewValidatorSetMessageForEra_exactEncoding() public view { + uint64 targetEra = 42; + bytes memory message = serviceManager.buildNewValidatorSetMessageForEra(targetEra); + + // Total: 4 (EL_MESSAGE_ID) + 1 (V0) + 1 (ReceiveValidators) + // + 1 (compact 10) + 10*20 (validators) + 8 (era) = 215 + assertEq(message.length, 215, "Message length should be 215 bytes"); + + // First 4 bytes: EL_MESSAGE_ID = 0x70150038 + assertEq(uint8(message[0]), 0x70, "EL_MESSAGE_ID byte 0"); + assertEq(uint8(message[1]), 0x15, "EL_MESSAGE_ID byte 1"); + assertEq(uint8(message[2]), 0x00, "EL_MESSAGE_ID byte 2"); + assertEq(uint8(message[3]), 0x38, "EL_MESSAGE_ID byte 3"); + + // Byte 4: V0 = 0x00 + assertEq(uint8(message[4]), 0x00, "V0 byte mismatch"); + + // Byte 5: ReceiveValidators = 0x00 + assertEq(uint8(message[5]), 0x00, "ReceiveValidators byte mismatch"); + + // Byte 6: SCALE compact encoding of 10 validators = 10 << 2 = 40 = 0x28 + assertEq(uint8(message[6]), 0x28, "Compact encoding of 10 validators"); + + // Last 8 bytes: era 42 in SCALE little-endian = 0x2A00000000000000 + assertEq(uint8(message[207]), 0x2A, "Era LE byte 0"); + assertEq(uint8(message[208]), 0x00, "Era LE byte 1"); + assertEq(uint8(message[209]), 0x00, "Era LE byte 2"); + assertEq(uint8(message[210]), 0x00, "Era LE byte 3"); + assertEq(uint8(message[211]), 0x00, "Era LE byte 4"); + assertEq(uint8(message[212]), 0x00, "Era LE byte 5"); + assertEq(uint8(message[213]), 0x00, "Era LE byte 6"); + assertEq(uint8(message[214]), 0x00, "Era LE byte 7"); + } + + // ============ Legacy function removed ============ + + function test_legacySendNewValidatorSet_removed() public { + // The old sendNewValidatorSet(uint128,uint128) selector should not be callable + bytes memory callData = + abi.encodeWithSelector(bytes4(keccak256("sendNewValidatorSet(uint128,uint128)")), 1, 1); + vm.deal(avsOwner, 10 ether); + cheats.prank(avsOwner); + (bool success,) = address(serviceManager).call{value: 2 ether}(callData); + assertFalse(success, "Legacy sendNewValidatorSet should not be callable"); + } +} diff --git a/contracts/test/storage/StorageLayout.t.sol b/contracts/test/storage/StorageLayout.t.sol new file mode 100644 index 00000000..69a3cd92 --- /dev/null +++ b/contracts/test/storage/StorageLayout.t.sol @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.27; + +import {Test} from "forge-std/Test.sol"; +import { + ITransparentUpgradeableProxy +} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +import {AVSDeployer} from "../utils/AVSDeployer.sol"; +import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol"; + +/// @title Storage Layout Tests for DataHavenServiceManager +/// @notice Verifies that proxy upgrades preserve state correctly +contract StorageLayoutTest is AVSDeployer { + function setUp() public { + _deployMockEigenLayerAndAVS(); + } + + /// @notice Proves state is preserved across proxy upgrade + function test_upgradePreservesState() public { + // 1. Populate state + address testValidator = address(0x1234); + address newRewardsInitiator = address(0x9999); + address testSubmitter = address(0x5678); + + vm.startPrank(avsOwner); + serviceManager.addValidatorToAllowlist(testValidator); + serviceManager.setRewardsInitiator(newRewardsInitiator); + serviceManager.setValidatorSetSubmitter(testSubmitter); + vm.stopPrank(); + + // 2. Record state before upgrade + bool allowlistBefore = serviceManager.validatorsAllowlist(testValidator); + address rewardsInitiatorBefore = serviceManager.rewardsInitiator(); + address ownerBefore = serviceManager.owner(); + address gatewayBefore = serviceManager.snowbridgeGateway(); + address submitterBefore = serviceManager.validatorSetSubmitter(); + + // 3. Deploy new implementation + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + // 4. Upgrade proxy + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // 5. Verify state preserved + assertEq( + serviceManager.validatorsAllowlist(testValidator), + allowlistBefore, + "validatorsAllowlist should be preserved" + ); + assertEq( + serviceManager.rewardsInitiator(), + rewardsInitiatorBefore, + "rewardsInitiator should be preserved" + ); + assertEq(serviceManager.owner(), ownerBefore, "owner should be preserved"); + assertEq( + serviceManager.snowbridgeGateway(), + gatewayBefore, + "snowbridgeGateway should be preserved" + ); + assertEq( + serviceManager.validatorSetSubmitter(), + submitterBefore, + "validatorSetSubmitter should be preserved" + ); + } + + /// @notice Verifies validatorEthAddressToSolochainAddress mapping is preserved + function test_upgradePreservesValidatorMappings() public { + address testValidator = address(0xABCD); + address testSolochainAddress = address(0xDEF0); + + // Add validator to allowlist first + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(testValidator); + + // Register operator via allocationManager to set the solochain address mapping + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = 0; // VALIDATORS_SET_ID + + vm.prank(address(allocationManager)); + serviceManager.registerOperator( + testValidator, + address(serviceManager), + operatorSetIds, + abi.encodePacked(testSolochainAddress) + ); + + // Record state before upgrade + bool inAllowlistBefore = serviceManager.validatorsAllowlist(testValidator); + address solochainAddressBefore = + serviceManager.validatorEthAddressToSolochainAddress(testValidator); + address ethOperatorBefore = + serviceManager.validatorSolochainAddressToEthAddress(testSolochainAddress); + + // Verify the mapping was set correctly before upgrade + assertEq(solochainAddressBefore, testSolochainAddress, "Solochain address should be set"); + assertEq(ethOperatorBefore, testValidator, "Eth operator should be set"); + + // Deploy new implementation and upgrade + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // Verify both mappings preserved after upgrade + assertEq( + serviceManager.validatorsAllowlist(testValidator), + inAllowlistBefore, + "validatorsAllowlist mapping should be preserved after upgrade" + ); + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(testValidator), + solochainAddressBefore, + "validatorEthAddressToSolochainAddress mapping should be preserved after upgrade" + ); + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(testValidator), + testSolochainAddress, + "validatorEthAddressToSolochainAddress should have correct value after upgrade" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(testSolochainAddress), + ethOperatorBefore, + "validatorSolochainAddressToEthAddress mapping should be preserved after upgrade" + ); + assertEq( + serviceManager.validatorSolochainAddressToEthAddress(testSolochainAddress), + testValidator, + "validatorSolochainAddressToEthAddress should have correct value after upgrade" + ); + } + + /// @notice Verifies multiple validators in allowlist are preserved + function test_upgradePreservesMultipleValidators() public { + address[] memory validators = new address[](3); + validators[0] = address(0x1111); + validators[1] = address(0x2222); + validators[2] = address(0x3333); + + // Add multiple validators + vm.startPrank(avsOwner); + for (uint256 i = 0; i < validators.length; i++) { + serviceManager.addValidatorToAllowlist(validators[i]); + } + vm.stopPrank(); + + // Deploy new implementation and upgrade + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // Verify all validators still in allowlist + for (uint256 i = 0; i < validators.length; i++) { + assertTrue( + serviceManager.validatorsAllowlist(validators[i]), + "All validators should remain in allowlist after upgrade" + ); + } + } + + /// @notice Verifies that upgrade doesn't affect functionality + function test_functionalityAfterUpgrade() public { + // Deploy new implementation and upgrade + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // Verify functionality still works + address newValidator = address(0xBEEF); + + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(newValidator); + + assertTrue( + serviceManager.validatorsAllowlist(newValidator), + "Should be able to add validators after upgrade" + ); + + vm.prank(avsOwner); + serviceManager.removeValidatorFromAllowlist(newValidator); + + assertFalse( + serviceManager.validatorsAllowlist(newValidator), + "Should be able to remove validators after upgrade" + ); + } +} diff --git a/contracts/test/utils/AVSDeployer.sol b/contracts/test/utils/AVSDeployer.sol index 13a4633d..ad3ba72d 100644 --- a/contracts/test/utils/AVSDeployer.sol +++ b/contracts/test/utils/AVSDeployer.sol @@ -48,11 +48,6 @@ contract AVSDeployer is Test { DataHavenServiceManager public serviceManager; DataHavenServiceManager public serviceManagerImplementation; - // Truncation is intentional - deriving a deterministic mock address from hash - address public vetoCommitteeMember = - address(uint160(uint256(keccak256("vetoCommitteeMember")))); - uint32 public vetoWindowBlocks = 100; // 100 blocks veto window for tests - // EigenLayer contracts StrategyManager public strategyManager; StrategyManager public strategyManagerImplementation; @@ -243,14 +238,6 @@ contract AVSDeployer is Test { serviceManagerImplementation = new DataHavenServiceManager(rewardsCoordinator, allocationManager); - // Create array for validators strategies required by DataHavenServiceManager - IStrategy[] memory validatorsStrategies = new IStrategy[](deployedStrategies.length); - - // For testing purposes, we'll use the deployed strategies for validators - for (uint256 i = 0; i < deployedStrategies.length; i++) { - validatorsStrategies[i] = deployedStrategies[i]; - } - serviceManager = DataHavenServiceManager( address( new TransparentUpgradeableProxy( @@ -260,8 +247,9 @@ contract AVSDeployer is Test { DataHavenServiceManager.initialize.selector, avsOwner, rewardsInitiator, - validatorsStrategies, - address(snowbridgeGatewayMock) + defaultStrategyAndMultipliers, + address(snowbridgeGatewayMock), + avsOwner ) ) ) diff --git a/contracts/test/utils/SnowbridgeAndAVSDeployer.sol b/contracts/test/utils/SnowbridgeAndAVSDeployer.sol index d0874122..f06babf7 100644 --- a/contracts/test/utils/SnowbridgeAndAVSDeployer.sol +++ b/contracts/test/utils/SnowbridgeAndAVSDeployer.sol @@ -16,6 +16,11 @@ import {TestUtils} from "./TestUtils.sol"; import { IAllocationManagerTypes } from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import { + IRewardsCoordinatorTypes +} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol"; +import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol"; import {ValidatorsUtils} from "../../script/utils/ValidatorsUtils.sol"; import {console} from "forge-std/Test.sol"; @@ -145,6 +150,61 @@ contract SnowbridgeAndAVSDeployer is AVSDeployer { serviceManager.setSnowbridgeGateway(address(gateway)); } + function setupValidatorsAsOperatorsWithAllocations() public { + setupValidatorsAsOperators(); + + // Remove strategies added during initialize (without multipliers) + // and re-add them with explicit multipliers + IStrategy[] memory strategies = new IStrategy[](deployedStrategies.length); + for (uint256 i = 0; i < deployedStrategies.length; i++) { + strategies[i] = deployedStrategies[i]; + } + + IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory sm = + new IRewardsCoordinatorTypes.StrategyAndMultiplier[](deployedStrategies.length); + for (uint256 i = 0; i < deployedStrategies.length; i++) { + sm[i] = IRewardsCoordinatorTypes.StrategyAndMultiplier({ + strategy: strategies[i], + multiplier: 1 // 1x multiplier for all strategies + }); + } + + cheats.startPrank(avsOwner); + serviceManager.removeStrategiesFromValidatorsSupportedStrategies(strategies); + serviceManager.addStrategiesToValidatorsSupportedStrategies(sm); + cheats.stopPrank(); + + // Advance past ALLOCATION_CONFIGURATION_DELAY (1 day = 86400 blocks in test setup) + // so operator allocation delays take effect + uint32 allocationConfigDelay = allocationManager.ALLOCATION_CONFIGURATION_DELAY(); + cheats.roll(block.number + allocationConfigDelay + 1); + + // For each operator, allocate full magnitude to the DataHaven operator set + for (uint256 i = 0; i < validatorsAllowlist.length; i++) { + IAllocationManagerTypes.AllocateParams[] memory allocParams = + new IAllocationManagerTypes.AllocateParams[](1); + + uint64[] memory newMagnitudes = new uint64[](deployedStrategies.length); + for (uint256 j = 0; j < deployedStrategies.length; j++) { + newMagnitudes[j] = 1e18; // 100% magnitude + } + + allocParams[0] = IAllocationManagerTypes.AllocateParams({ + operatorSet: OperatorSet({ + avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID() + }), + strategies: strategies, + newMagnitudes: newMagnitudes + }); + + cheats.prank(validatorsAllowlist[i]); + allocationManager.modifyAllocations(validatorsAllowlist[i], allocParams); + } + + // Advance past allocation effect delay (operator delay is 0, so just +1 block) + cheats.roll(block.number + 1); + } + function setupValidatorsAsOperators() public { for (uint256 i = 0; i < validatorsAllowlist.length; i++) { console.log("Setting up validator %s as operator", validatorsAllowlist[i]); diff --git a/operator/Cargo.lock b/operator/Cargo.lock index 652aa154..59a43614 100644 --- a/operator/Cargo.lock +++ b/operator/Cargo.lock @@ -1176,7 +1176,7 @@ dependencies = [ "bitflags 2.9.4", "cexpr", "clang-sys", - "itertools 0.11.0", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -1521,7 +1521,7 @@ dependencies = [ "pallet-message-queue", "parity-scale-codec", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "sp-core", "sp-runtime", "sp-std", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "datahaven-mainnet-runtime" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "bridge-hub-common 0.13.1", @@ -2629,6 +2629,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itoa", + "k256", "log", "num-bigint", "num_enum", @@ -2718,8 +2719,8 @@ dependencies = [ "shp-treasury-funding", "shp-tx-implicits-runtime-api", "smallvec", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -2762,7 +2763,7 @@ dependencies = [ [[package]] name = "datahaven-node" -version = "0.21.0" +version = "0.25.0" dependencies = [ "async-channel 1.9.0", "clap", @@ -2790,6 +2791,7 @@ dependencies = [ "hex-literal 0.3.4", "jsonrpsee 0.24.9", "log", + "mmr-gadget", "mmr-rpc", "openssl-sys", "pallet-beefy-mmr", @@ -2859,6 +2861,7 @@ dependencies = [ "sp-io", "sp-keyring", "sp-keystore", + "sp-mmr-primitives", "sp-offchain", "sp-runtime", "sp-session", @@ -2873,7 +2876,7 @@ dependencies = [ [[package]] name = "datahaven-runtime-common" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "fp-account", @@ -2907,7 +2910,7 @@ dependencies = [ [[package]] name = "datahaven-stagenet-runtime" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "bridge-hub-common 0.13.1", @@ -2929,6 +2932,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itoa", + "k256", "log", "num-bigint", "num_enum", @@ -3018,8 +3022,8 @@ dependencies = [ "shp-treasury-funding", "shp-tx-implicits-runtime-api", "smallvec", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3062,7 +3066,7 @@ dependencies = [ [[package]] name = "datahaven-testnet-runtime" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "bridge-hub-common 0.13.1", @@ -3084,6 +3088,7 @@ dependencies = [ "hex", "hex-literal 0.3.4", "itoa", + "k256", "log", "num-bigint", "num_enum", @@ -3173,8 +3178,8 @@ dependencies = [ "shp-treasury-funding", "shp-tx-implicits-runtime-api", "smallvec", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3366,7 +3371,7 @@ dependencies = [ [[package]] name = "dhp-bridge" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-support", "frame-system", @@ -3374,7 +3379,7 @@ dependencies = [ "pallet-datahaven-native-transfer", "pallet-external-validators", "parity-scale-codec", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -3864,7 +3869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5766,7 +5771,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core 0.61.2", ] [[package]] @@ -6215,15 +6220,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.15" @@ -7722,6 +7718,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "mmr-gadget" +version = "43.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +dependencies = [ + "futures", + "log", + "parity-scale-codec", + "sc-client-api", + "sc-offchain", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-consensus-beefy", + "sp-core", + "sp-mmr-primitives", + "sp-runtime", +] + [[package]] name = "mmr-rpc" version = "39.0.0" @@ -8259,7 +8274,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ - "proc-macro-crate 1.1.3", + "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 2.0.106", @@ -8624,8 +8639,8 @@ dependencies = [ [[package]] name = "pallet-bucket-nfts" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-benchmarking", "frame-support", @@ -8681,8 +8696,8 @@ dependencies = [ [[package]] name = "pallet-cr-randomness" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-support", "frame-system", @@ -8701,7 +8716,7 @@ dependencies = [ [[package]] name = "pallet-datahaven-native-transfer" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -8709,7 +8724,7 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -8813,7 +8828,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-balances-erc20" -version = "0.21.0" +version = "0.25.0" dependencies = [ "fp-evm", "frame-support", @@ -8836,7 +8851,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-batch" -version = "0.21.0" +version = "0.25.0" dependencies = [ "evm", "fp-evm", @@ -8875,7 +8890,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-call-permit" -version = "0.21.0" +version = "0.25.0" dependencies = [ "evm", "fp-evm", @@ -8941,7 +8956,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-datahaven-native-transfer" -version = "0.21.0" +version = "0.25.0" dependencies = [ "evm", "fp-evm", @@ -8955,7 +8970,7 @@ dependencies = [ "parity-scale-codec", "precompile-utils", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -8965,8 +8980,8 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-file-system" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "fp-account", "fp-evm", @@ -9034,7 +9049,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-proxy" -version = "0.21.0" +version = "0.25.0" dependencies = [ "evm", "fp-evm", @@ -9078,7 +9093,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-registry" -version = "0.21.0" +version = "0.25.0" dependencies = [ "fp-evm", "frame-support", @@ -9129,7 +9144,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -9139,7 +9154,7 @@ dependencies = [ [[package]] name = "pallet-external-validators" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -9163,7 +9178,7 @@ dependencies = [ [[package]] name = "pallet-external-validators-rewards" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -9176,7 +9191,7 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -9205,12 +9220,13 @@ dependencies = [ [[package]] name = "pallet-file-system" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex", "log", "num-bigint", "pallet-file-system-runtime-api", @@ -9221,6 +9237,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "shp-constants", + "shp-file-key-verifier", "shp-file-metadata", "shp-traits", "sp-core", @@ -9232,8 +9249,8 @@ dependencies = [ [[package]] name = "pallet-file-system-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "parity-scale-codec", "scale-info", @@ -9400,7 +9417,7 @@ dependencies = [ [[package]] name = "pallet-outbound-commitment-store" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-support", "frame-system", @@ -9428,8 +9445,8 @@ dependencies = [ [[package]] name = "pallet-payment-streams" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-benchmarking", "frame-support", @@ -9448,8 +9465,8 @@ dependencies = [ [[package]] name = "pallet-payment-streams-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "parity-scale-codec", "scale-info", @@ -9476,17 +9493,21 @@ dependencies = [ [[package]] name = "pallet-proofs-dealer" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex", "pallet-balances", "pallet-proofs-dealer-runtime-api", "pallet-storage-providers", "parity-scale-codec", "scale-info", + "shp-file-key-verifier", + "shp-file-metadata", + "shp-forest-verifier", "shp-traits", "sp-core", "sp-keyring", @@ -9498,8 +9519,8 @@ dependencies = [ [[package]] name = "pallet-proofs-dealer-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "parity-scale-codec", "scale-info", @@ -9520,7 +9541,7 @@ dependencies = [ [[package]] name = "pallet-proxy-genesis-companion" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-support", "frame-system", @@ -9537,8 +9558,8 @@ dependencies = [ [[package]] name = "pallet-randomness" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-benchmarking", "frame-support", @@ -9631,18 +9652,15 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" -version = "39.1.0" -source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-stable2412-6#bbc435c7667d3283ba280a8fec44676357392753" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "pallet-session", - "pallet-staking", "parity-scale-codec", - "rand 0.8.5", "sp-runtime", - "sp-session", + "sp-std", ] [[package]] @@ -9678,8 +9696,8 @@ dependencies = [ [[package]] name = "pallet-storage-providers" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-benchmarking", "frame-support", @@ -9700,8 +9718,8 @@ dependencies = [ [[package]] name = "pallet-storage-providers-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "parity-scale-codec", "scale-info", @@ -11104,7 +11122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", + "heck 0.5.0", "itertools 0.12.1", "log", "multimap", @@ -11124,8 +11142,8 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.4.1", - "itertools 0.14.0", + "heck 0.5.0", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -11158,7 +11176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.106", @@ -11918,7 +11936,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -13863,8 +13881,8 @@ dependencies = [ [[package]] name = "shc-actors-derive" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "once_cell", "proc-macro2", @@ -13876,8 +13894,8 @@ dependencies = [ [[package]] name = "shc-actors-framework" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "bincode", @@ -13895,8 +13913,8 @@ dependencies = [ [[package]] name = "shc-blockchain-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "array-bytes", @@ -13951,8 +13969,8 @@ dependencies = [ [[package]] name = "shc-blockchain-service-db" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "chrono", "diesel", @@ -13975,8 +13993,8 @@ dependencies = [ [[package]] name = "shc-client" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "array-bytes", @@ -14049,8 +14067,8 @@ dependencies = [ [[package]] name = "shc-common" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "bigdecimal", @@ -14113,8 +14131,8 @@ dependencies = [ [[package]] name = "shc-file-manager" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "bincode", "hash-db", @@ -14137,8 +14155,8 @@ dependencies = [ [[package]] name = "shc-file-transfer-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "array-bytes", @@ -14166,8 +14184,8 @@ dependencies = [ [[package]] name = "shc-fisherman-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "async-trait", "diesel", @@ -14197,8 +14215,8 @@ dependencies = [ [[package]] name = "shc-forest-manager" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "async-trait", @@ -14223,8 +14241,8 @@ dependencies = [ [[package]] name = "shc-indexer-db" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "bigdecimal", "chrono", @@ -14251,8 +14269,8 @@ dependencies = [ [[package]] name = "shc-indexer-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "anyhow", "array-bytes", @@ -14302,8 +14320,8 @@ dependencies = [ [[package]] name = "shc-rpc" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "array-bytes", "async-trait", @@ -14348,8 +14366,8 @@ dependencies = [ [[package]] name = "shc-telemetry" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -14365,8 +14383,8 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "shp-constants" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "sp-core", "sp-runtime", @@ -14374,8 +14392,8 @@ dependencies = [ [[package]] name = "shp-data-price-updater" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-support", "parity-scale-codec", @@ -14389,8 +14407,8 @@ dependencies = [ [[package]] name = "shp-file-key-verifier" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-support", "parity-scale-codec", @@ -14407,8 +14425,8 @@ dependencies = [ [[package]] name = "shp-file-metadata" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "hex", "num-bigint", @@ -14423,8 +14441,8 @@ dependencies = [ [[package]] name = "shp-forest-verifier" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-support", "parity-scale-codec", @@ -14440,16 +14458,16 @@ dependencies = [ [[package]] name = "shp-opaque" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "sp-runtime", ] [[package]] name = "shp-session-keys" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "async-trait", "parity-scale-codec", @@ -14463,8 +14481,8 @@ dependencies = [ [[package]] name = "shp-traits" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "frame-support", "parity-scale-codec", @@ -14477,8 +14495,8 @@ dependencies = [ [[package]] name = "shp-treasury-funding" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "log", "shp-traits", @@ -14488,8 +14506,8 @@ dependencies = [ [[package]] name = "shp-tx-implicits-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "parity-scale-codec", "scale-info", @@ -14501,8 +14519,8 @@ dependencies = [ [[package]] name = "shp-types" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.1" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.1#b5d6eb2ffa153d97e079d1fda382773b466f4702" dependencies = [ "sp-core", "sp-runtime", @@ -14782,7 +14800,7 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.21.0" +version = "0.25.0" dependencies = [ "byte-slice-cast", "frame-support", @@ -14827,7 +14845,7 @@ dependencies = [ [[package]] name = "snowbridge-core" -version = "0.21.0" +version = "0.25.0" dependencies = [ "bp-relayers", "ethabi-decode", @@ -14904,8 +14922,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-verification-primitives", "sp-core", "sp-io", @@ -14918,7 +14936,7 @@ dependencies = [ [[package]] name = "snowbridge-merkle-tree" -version = "0.21.0" +version = "0.25.0" dependencies = [ "array-bytes", "hex", @@ -14959,7 +14977,7 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-primitives" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "ethabi-decode", @@ -14971,7 +14989,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-verification-primitives", "sp-arithmetic", "sp-core", @@ -14985,12 +15003,12 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-v2-runtime-api" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", "sp-api", @@ -15000,7 +15018,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-ethereum-client" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -15013,8 +15031,8 @@ dependencies = [ "scale-info", "serde", "serde_json", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-ethereum 0.3.0", "snowbridge-inbound-queue-primitives", "snowbridge-pallet-ethereum-client-fixtures", @@ -15030,8 +15048,8 @@ name = "snowbridge-pallet-ethereum-client-fixtures" version = "0.9.0" dependencies = [ "hex-literal 0.3.4", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -15039,7 +15057,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-inbound-queue-v2" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "bp-relayers", @@ -15053,8 +15071,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-inbound-queue-v2-fixtures", @@ -15075,8 +15093,8 @@ name = "snowbridge-pallet-inbound-queue-v2-fixtures" version = "0.10.0" dependencies = [ "hex-literal 0.3.4", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -15106,7 +15124,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-outbound-queue-v2" -version = "0.21.0" +version = "0.25.0" dependencies = [ "alloy-core", "bp-relayers", @@ -15120,8 +15138,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-beacon-primitives 0.21.0", - "snowbridge-core 0.21.0", + "snowbridge-beacon-primitives 0.25.0", + "snowbridge-core 0.25.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -15152,7 +15170,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-outbound-queue-primitives", "snowbridge-pallet-outbound-queue", "sp-core", @@ -15165,7 +15183,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-system-v2" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -15177,7 +15195,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "snowbridge-outbound-queue-primitives", "snowbridge-pallet-outbound-queue-v2", "snowbridge-pallet-system", @@ -15193,10 +15211,10 @@ dependencies = [ [[package]] name = "snowbridge-system-v2-runtime-api" -version = "0.21.0" +version = "0.25.0" dependencies = [ "parity-scale-codec", - "snowbridge-core 0.21.0", + "snowbridge-core 0.25.0", "sp-api", "sp-std", "staging-xcm", @@ -15204,7 +15222,7 @@ dependencies = [ [[package]] name = "snowbridge-test-utils" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -15224,12 +15242,12 @@ dependencies = [ [[package]] name = "snowbridge-verification-primitives" -version = "0.21.0" +version = "0.25.0" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "snowbridge-beacon-primitives 0.21.0", + "snowbridge-beacon-primitives 0.25.0", "sp-core", "sp-std", ] @@ -16810,7 +16828,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.1.2", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -18416,7 +18434,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -18477,20 +18495,7 @@ dependencies = [ "windows-interface", "windows-link 0.1.3", "windows-result 0.3.4", - "windows-strings 0.4.2", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", + "windows-strings", ] [[package]] @@ -18566,15 +18571,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-strings" version = "0.4.2" @@ -18584,15 +18580,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-sys" version = "0.45.0" diff --git a/operator/Cargo.toml b/operator/Cargo.toml index 31eaf63c..169d361b 100644 --- a/operator/Cargo.toml +++ b/operator/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" homepage = "https://datahaven.xyz/" license = "GPL-3" repository = "https://github.com/datahavenxyz/datahaven" -version = "0.21.0" +version = "0.25.0" [workspace] members = [ @@ -44,6 +44,7 @@ pallet-external-validators = { path = "./pallets/external-validators", default-f pallet-external-validators-rewards = { path = "./pallets/external-validators-rewards", default-features = false } pallet-outbound-commitment-store = { path = "./pallets/outbound-commitment-store", default-features = false } pallet-proxy-genesis-companion = { path = "./pallets/proxy-genesis-companion", default-features = false } +pallet-session-benchmarking = { path = "./pallets/session-benchmarking", default-features = false } # Crates.io (wasm) alloy-core = { version = "0.8.15", default-features = false } @@ -67,6 +68,10 @@ impl-serde = { version = "0.5.0", default-features = false } impl-trait-for-tuples = { version = "0.2.2" } itoa = { version = "1.0" } jsonrpsee = { version = "0.24.3" } +k256 = { version = "0.13.4", default-features = false, features = [ + "ecdsa", + "alloc", +] } libsecp256k1 = { version = "0.7", default-features = false } log = { version = "0.4.25" } macro_rules_attribute = { version = "0.2.0" } @@ -113,6 +118,7 @@ frame-system = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polk frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } +mmr-gadget = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } mmr-rpc = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-assets = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } @@ -139,7 +145,6 @@ pallet-referenda = { git = "https://github.com/paritytech/polkadot-sdk", tag = " pallet-safe-mode = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } -pallet-session-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-staking = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } @@ -191,6 +196,7 @@ sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polk sp-io = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } +sp-mmr-primitives = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-stable2412-6", default-features = false } @@ -266,42 +272,42 @@ fc-storage = { git = "https://github.com/polkadot-evm/frontier", branch = "stabl # StorageHub ## Runtime -pallet-bucket-nfts = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-cr-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-file-system-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-payment-streams = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-payment-streams-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-proofs-dealer = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-proofs-dealer-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-storage-providers = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-storage-providers-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-constants = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-data-price-updater = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-file-key-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-file-metadata = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-forest-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-traits = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-treasury-funding = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } +pallet-bucket-nfts = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-cr-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-file-system-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-payment-streams = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-payment-streams-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-proofs-dealer = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-proofs-dealer-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-storage-providers = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +pallet-storage-providers-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-constants = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-data-price-updater = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-file-key-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-file-metadata = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-forest-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-traits = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-treasury-funding = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } ## Client -shc-actors-derive = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-actors-framework = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-blockchain-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-client = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-common = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-file-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-file-transfer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-fisherman-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-forest-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-indexer-db = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-indexer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-rpc = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-opaque = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-tx-implicits-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-types = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } +shc-actors-derive = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-actors-framework = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-blockchain-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-client = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-common = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-file-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-file-transfer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-fisherman-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-forest-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-indexer-db = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-indexer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shc-rpc = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-opaque = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-tx-implicits-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } +shp-types = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } ## Precompiles -pallet-evm-precompile-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } +pallet-evm-precompile-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.1", default-features = false } # Static linking diff --git a/operator/benchmarking/frame-weight-template.hbs b/operator/benchmarking/frame-weight-template.hbs index f9508559..9fcc72c5 100644 --- a/operator/benchmarking/frame-weight-template.hbs +++ b/operator/benchmarking/frame-weight-template.hbs @@ -19,7 +19,6 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -use crate::{{pallet}}; /// Weights for `{{pallet}}`. pub struct WeightInfo(PhantomData); diff --git a/operator/node/Cargo.toml b/operator/node/Cargo.toml index 00bf7da0..68861344 100644 --- a/operator/node/Cargo.toml +++ b/operator/node/Cargo.toml @@ -35,9 +35,11 @@ serde_json = { workspace = true, default-features = true } url = { workspace = true } #MMR +mmr-gadget = { workspace = true, default-features = true } mmr-rpc = { workspace = true, default-features = true } pallet-beefy-mmr = { workspace = true, default-features = true } pallet-mmr = { workspace = true, default-features = true } +sp-mmr-primitives = { workspace = true, default-features = true } # Polkadot SDK frame-benchmarking-cli = { workspace = true, default-features = true, optional = true } @@ -139,7 +141,6 @@ toml = { workspace = true } #### Needed to build static binaries #### pq-sys = { workspace = true, optional = true } - [build-dependencies] substrate-build-script-utils = { workspace = true, default-features = true } diff --git a/operator/node/src/cli.rs b/operator/node/src/cli.rs index 1573aa77..af0ac8af 100644 --- a/operator/node/src/cli.rs +++ b/operator/node/src/cli.rs @@ -242,6 +242,16 @@ pub struct ProviderConfigurations { #[arg(long, default_value = "60")] pub extrinsic_retry_timeout: Option, + /// Mortality period for extrinsics in number of blocks. + /// + /// Determines how long a submitted transaction remains valid before expiring. + /// Must be a power of 2 between 4 and `BlockHashCount` (4096). Non-power-of-2 values + /// will be rounded up to the next valid power of 2. Lower values mean transactions + /// expire faster, which helps recover from stuck nonces after block reorgs, but also + /// reduces the window for a transaction to be included on-chain. + #[arg(long, value_name = "BLOCKS", default_value = "256", value_parser = clap::value_parser!(u32).range(4..))] + pub extrinsic_mortality: Option, + /// On blocks that are multiples of this number, the blockchain service will trigger the catch of proofs. #[arg(long, default_value = "4")] pub check_for_pending_proofs_period: Option, @@ -607,6 +617,11 @@ impl ProviderConfigurations { bs_changed = true; } + if let Some(extrinsic_mortality) = self.extrinsic_mortality { + bs_options.extrinsic_mortality = Some(extrinsic_mortality); + bs_changed = true; + } + if let Some(check_for_pending_proofs_period) = self.check_for_pending_proofs_period { bs_options.check_for_pending_proofs_period = Some(check_for_pending_proofs_period); bs_changed = true; @@ -741,9 +756,23 @@ pub struct FishermanConfigurations { pub fisherman_database_url: Option, /// Duration between batch deletion processing cycles (in seconds). - #[arg(long, default_value = "60", value_parser = clap::value_parser!(u64).range(1..))] + #[arg(long, default_value = "30", value_parser = clap::value_parser!(u64).range(1..))] pub fisherman_batch_interval_seconds: u64, + /// Cooldown between batch deletion attempts (in seconds). + /// + /// Set to `0` to disable cooldown. + #[arg(long, default_value = "1", value_parser = clap::value_parser!(u64).range(0..))] + pub fisherman_batch_cooldown_seconds: u64, + + /// Number of consecutive no-work batches required before switching to the slower idle polling interval. + /// + /// The minimum value is 2 because there are two kinds of work: User and Incomplete. + /// If we set the value to 1, a non-work batch in one kind of work will trigger the idle poll interval + /// on the other kind of work. + #[arg(long, default_value = "4", value_parser = clap::value_parser!(u8).range(1..))] + pub fisherman_consecutive_no_work_batches_threshold: u8, + /// Maximum number of files to process per batch deletion cycle. #[arg(long, default_value = "1000", value_parser = clap::value_parser!(u64).range(1..))] pub fisherman_batch_deletion_limit: u64, @@ -776,6 +805,16 @@ pub struct FishermanConfigurations { help_heading = "Fisherman Strategy Options" )] pub fisherman_ttl_threshold_seconds: Option, + + /// Mortality period for extrinsics in number of blocks. + /// + /// Determines how long a submitted transaction remains valid before expiring. + /// Must be a power of 2 between 4 and BlockHashCount (4096). Non-power-of-2 values + /// will be rounded to the nearest valid power of 2. Lower values mean transactions + /// expire faster, which helps recover from stuck nonces after block reorgs, but also + /// reduces the window for a transaction to be included. + #[arg(long, value_name = "BLOCKS", default_value = "256", value_parser = clap::value_parser!(u32).range(4..))] + pub fisherman_extrinsic_mortality: Option, } impl FishermanConfigurations { @@ -796,6 +835,20 @@ impl FishermanConfigurations { FishermanOrdering::Randomized => FileOrdering::Randomized, }; + // Build blockchain_service options + let mut blockchain_service = None; + let mut bs_options = BlockchainServiceOptions::default(); + let mut bs_changed = false; + + if let Some(extrinsic_mortality) = self.fisherman_extrinsic_mortality { + bs_options.extrinsic_mortality = Some(extrinsic_mortality); + bs_changed = true; + } + + if bs_changed { + blockchain_service = Some(bs_options); + } + Some(FishermanOptions { database_url: self .fisherman_database_url @@ -803,9 +856,13 @@ impl FishermanConfigurations { .expect("Fisherman database URL is required"), batch_interval_seconds: self.fisherman_batch_interval_seconds, batch_deletion_limit: self.fisherman_batch_deletion_limit, + batch_cooldown_seconds: self.fisherman_batch_cooldown_seconds, + consecutive_no_work_batches_threshold: self + .fisherman_consecutive_no_work_batches_threshold, maintenance_mode: false, // Skipping maintenance mode for now filtering, ordering, + blockchain_service, }) } else { None diff --git a/operator/node/src/rpc.rs b/operator/node/src/rpc.rs index 81d59467..25380cdb 100644 --- a/operator/node/src/rpc.rs +++ b/operator/node/src/rpc.rs @@ -24,10 +24,13 @@ use crate::consensus::BabeConsensusDataProvider; use crate::eth::DefaultEthConfig; use datahaven_runtime_common::{time::SLOT_DURATION, Block, BlockNumber, Hash}; -use fc_rpc::TxPool; use fc_rpc::{Eth, EthBlockDataCacheTask, EthFilter, Net, Web3}; +use fc_rpc::{EthPubSub, TxPool}; use fc_rpc_core::types::{FeeHistoryCache, FilterPool}; -use fc_rpc_core::{EthApiServer, EthFilterApiServer, NetApiServer, TxPoolApiServer, Web3ApiServer}; +use fc_rpc_core::{ + EthApiServer, EthFilterApiServer, EthPubSubApiServer, NetApiServer, TxPoolApiServer, + Web3ApiServer, +}; use fc_storage::StorageOverride; use fp_rpc::EthereumRuntimeRPCApi; use jsonrpsee::RpcModule; @@ -111,6 +114,12 @@ where /// Instantiate all full RPC extensions. pub fn create_full( deps: FullDeps, + subscription_task_executor: sc_rpc::SubscriptionTaskExecutor, + pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, ) -> Result, Box> where P: TransactionPool + 'static, @@ -263,6 +272,17 @@ where )?; module.merge(Web3::new(Arc::clone(&client)).into_rpc())?; + module.merge( + EthPubSub::new( + pool, + Arc::clone(&client), + sync.clone(), + subscription_task_executor, + overrides, + pubsub_notification_sinks.clone(), + ) + .into_rpc(), + )?; if let Some(command_sink) = command_sink { module.merge( @@ -275,19 +295,5 @@ where let tx_pool = TxPool::new(client.clone(), graph.clone()); module.merge(tx_pool.into_rpc())?; - // module.merge(FrontierFinality::new(client.clone(), frontier_backend.clone()).into_rpc())?; - - // Extend this RPC with a custom API by using the following syntax. - // `YourRpcStruct` should have a reference to a client, which is needed - // to call into the runtime. - // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` - - // You probably want to enable the `rpc v2 chainSpec` API as well - // - // let chain_name = chain_spec.name().to_string(); - // let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); - // let properties = chain_spec.properties(); - // module.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?; - Ok(module) } diff --git a/operator/node/src/service.rs b/operator/node/src/service.rs index fe92dbfd..b203e7c7 100644 --- a/operator/node/src/service.rs +++ b/operator/node/src/service.rs @@ -72,6 +72,7 @@ use sp_api::ProvideRuntimeApi; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; use sp_keystore::KeystorePtr; +use sp_mmr_primitives::INDEXING_PREFIX; use sp_runtime::traits::BlakeTwo256; use sp_runtime::SaturatedConversion; use std::path::PathBuf; @@ -438,7 +439,7 @@ pub async fn new_full_impl< RuntimeApi, N: sc_network::NetworkBackend::Hash>, >( - config: Configuration, + mut config: Configuration, mut eth_config: EthConfiguration, role_options: Option, indexer_options: Option, @@ -452,6 +453,9 @@ where StorageHubBuilder: StorageLayerBuilder + Buildable<(R, S), Runtime>, StorageHubHandler<(R, S), Runtime>: RunnableTasks, { + let enable_offchain_worker = config.offchain_worker.enabled; + let is_offchain_indexing_enabled = config.offchain_worker.indexing_enabled; + let role = config.role; let mut sealing = match sealing { Some(_) if !matches!(config.chain_spec.chain_type(), ChainType::Development) => { @@ -582,7 +586,7 @@ where metrics, })?; - if config.offchain_worker.enabled { + if enable_offchain_worker { task_manager.spawn_handle().spawn( "offchain-workers-runner", "offchain-worker", @@ -669,7 +673,7 @@ where }, storage_override, sync: sync_service.clone(), - pubsub_notification_sinks, + pubsub_notification_sinks: pubsub_notification_sinks.clone(), }, ) .await; @@ -689,38 +693,52 @@ where let fee_history_limit = eth_config.fee_history_limit; let sync = sync_service.clone(); - Box::new(move |subscription_executor| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: pool.clone(), - graph: pool.pool().clone(), - beefy: BeefyDeps:: { - beefy_finality_proof_stream: beefy_rpc_links.from_voter_justif_stream.clone(), - beefy_best_block_stream: beefy_rpc_links.from_voter_best_beefy_stream.clone(), + Box::new( + move |subscription_executor: sc_rpc::SubscriptionTaskExecutor| { + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + graph: pool.pool().clone(), + beefy: BeefyDeps:: { + beefy_finality_proof_stream: beefy_rpc_links + .from_voter_justif_stream + .clone(), + beefy_best_block_stream: beefy_rpc_links + .from_voter_best_beefy_stream + .clone(), + subscription_executor: subscription_executor.clone(), + }, + max_past_logs, + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), + network: Arc::new(network.clone()), + sync: sync.clone(), + filter_pool: filter_pool.clone(), + block_data_cache: block_data_cache.clone(), + overrides: overrides.clone(), + is_authority: is_authority.clone(), + command_sink: command_sink.clone(), + backend: backend.clone(), + frontier_backend: match &*frontier_backend { + fc_db::Backend::KeyValue(b) => b.clone(), + fc_db::Backend::Sql(b) => b.clone(), + }, + forced_parent_hashes: None, + maybe_storage_hub_client_config: maybe_storage_hub_client_rpc_config.clone(), + }; + crate::rpc::create_full( + deps, subscription_executor, - }, - max_past_logs, - fee_history_limit, - fee_history_cache: fee_history_cache.clone(), - network: Arc::new(network.clone()), - sync: sync.clone(), - filter_pool: filter_pool.clone(), - block_data_cache: block_data_cache.clone(), - overrides: overrides.clone(), - is_authority: is_authority.clone(), - command_sink: command_sink.clone(), - backend: backend.clone(), - frontier_backend: match &*frontier_backend { - fc_db::Backend::KeyValue(b) => b.clone(), - fc_db::Backend::Sql(b) => b.clone(), - }, - forced_parent_hashes: None, - maybe_storage_hub_client_config: maybe_storage_hub_client_rpc_config.clone(), - }; - crate::rpc::create_full(deps).map_err(Into::into) - }) + pubsub_notification_sinks.clone(), + ) + .map_err(Into::into) + }, + ) }; + // Use Ethereum-style hex subscription IDs (0x-prefixed) instead of jsonrpsee defaults. + config.rpc.id_provider = Some(Box::new(fc_rpc::EthereumSubIdProvider)); + let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: Arc::new(network.clone()), client: client.clone(), @@ -948,6 +966,22 @@ where .spawn_essential_handle() .spawn_blocking("beefy-gadget", None, gadget); } + + // Spawn MMR gadget for offchain MMR leaf indexing. + // This gadget monitors finality and canonicalizes MMR data in offchain storage, + // enabling efficient MMR proof queries by block number via the MMR RPC. + // Only run when offchain indexing is enabled, as the gadget writes to offchain storage. + if is_offchain_indexing_enabled { + task_manager.spawn_essential_handle().spawn_blocking( + "mmr-gadget", + None, + mmr_gadget::MmrGadget::start( + client.clone(), + backend.clone(), + INDEXING_PREFIX.to_vec(), + ), + ); + } } if let Some(_) = role_options { @@ -1271,6 +1305,11 @@ where // Set the indexer db pool builder.with_indexer_db_pool(Some(db_pool)); + // Configure blockchain service options for the fisherman + if let Some(c) = fisherman_options.blockchain_service.clone() { + builder.with_blockchain_service_config(c); + } + // Spawn the fisherman service builder .with_fisherman(client.clone(), &fisherman_options) diff --git a/operator/pallets/external-validators/src/lib.rs b/operator/pallets/external-validators/src/lib.rs index 5602f78d..7b2fdaf5 100644 --- a/operator/pallets/external-validators/src/lib.rs +++ b/operator/pallets/external-validators/src/lib.rs @@ -309,6 +309,12 @@ pub mod pallet { NoKeysRegistered, /// Unable to derive validator id from account id UnableToDeriveValidatorId, + /// The target era is too old (targetEra <= ActiveEra). Message arrived late. + TargetEraTooOld, + /// The target era is too far ahead (targetEra > ActiveEra + 1). + TargetEraTooNew, + /// The target era has already been seen (targetEra <= ExternalIndex). Duplicate or stale. + DuplicateOrStaleTargetEra, } #[pallet::call] @@ -419,6 +425,9 @@ pub mod pallet { validators: Vec, external_index: u64, ) -> DispatchResult { + // Validate the target era before accepting the validator set + Self::validate_target_era(external_index)?; + // If more validators than max, take the first n let validators = BoundedVec::truncate_from(validators); >::put(&validators); @@ -431,6 +440,27 @@ pub mod pallet { Ok(()) } + fn validate_target_era(target_era: u64) -> DispatchResult { + let active_era_index = Self::active_era() + .map(|info| info.index as u64) + .unwrap_or(0); + let current_external_index = ExternalIndex::::get(); + + // Must target exactly the next era + if target_era <= active_era_index { + return Err(Error::::TargetEraTooOld.into()); + } + if target_era > active_era_index + 1 { + return Err(Error::::TargetEraTooNew.into()); + } + // Dedupe/stale guard + if target_era <= current_external_index { + return Err(Error::::DuplicateOrStaleTargetEra.into()); + } + + Ok(()) + } + /// Helper to set a new `ForceEra` mode. pub(crate) fn set_force_era(mode: Forcing) { log::info!("Setting force era mode {:?}.", mode); diff --git a/operator/pallets/external-validators/src/tests.rs b/operator/pallets/external-validators/src/tests.rs index b25d5ab1..e37bc582 100644 --- a/operator/pallets/external-validators/src/tests.rs +++ b/operator/pallets/external-validators/src/tests.rs @@ -345,10 +345,96 @@ fn era_hooks() { }); } +#[test] +fn target_era_validation_accepts_next_era() { + new_test_ext().execute_with(|| { + // Advance to era 1 (session 6 starts era 1) + run_to_session(6); + + // ActiveEra is now 1, so target era 2 (ActiveEra + 1) should succeed + assert_ok!(ExternalValidators::set_external_validators_inner( + vec![50, 51], + 2 + )); + }); +} + +#[test] +fn target_era_validation_rejects_old_era() { + new_test_ext().execute_with(|| { + // Advance to era 1 + run_to_session(6); + + // target_era = 0 (ActiveEra - 1) should fail + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 0), + Error::::TargetEraTooOld + ); + + // target_era = 1 (== ActiveEra) should also fail + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 1), + Error::::TargetEraTooOld + ); + }); +} + +#[test] +fn target_era_validation_rejects_too_new_era() { + new_test_ext().execute_with(|| { + // Advance to era 1 + run_to_session(6); + + // target_era = 3 (ActiveEra + 2) should fail + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 3), + Error::::TargetEraTooNew + ); + }); +} + +#[test] +fn target_era_validation_rejects_duplicate() { + new_test_ext().execute_with(|| { + // Advance to era 1 + run_to_session(6); + + // First submission with target_era = 2 should succeed + assert_ok!(ExternalValidators::set_external_validators_inner( + vec![50, 51], + 2 + )); + + // Second submission with same target_era = 2 should fail (duplicate) + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 2), + Error::::DuplicateOrStaleTargetEra + ); + }); +} + +#[test] +fn target_era_validation_at_genesis() { + new_test_ext().execute_with(|| { + // At genesis, ActiveEra = 0, so target_era = 1 (ActiveEra + 1) should succeed + assert_ok!(ExternalValidators::set_external_validators_inner( + vec![50, 51], + 1 + )); + + // target_era = 0 should fail (too old, <= ActiveEra) + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 0), + Error::::TargetEraTooOld + ); + }); +} + #[test] fn era_hooks_with_external_index() { new_test_ext().execute_with(|| { - let first_external_index = 1000; + // ActiveEra starts at 0, so target era 1 (ActiveEra + 1) is valid + let first_external_index = 1; assert_ok!(ExternalValidators::set_external_validators_inner( vec![50, 51], first_external_index @@ -356,7 +442,8 @@ fn era_hooks_with_external_index() { run_to_session(8); - let second_external_index = 2000; + // ActiveEra is now 1, so target era 2 (ActiveEra + 1) is valid + let second_external_index = 2; assert_ok!(ExternalValidators::set_external_validators_inner( vec![50, 51], @@ -388,3 +475,81 @@ fn era_hooks_with_external_index() { assert_eq!(Mock::mock().called_hooks, expected_calls); }); } + +#[test] +fn set_external_validators_extrinsic_rejects_bad_origin() { + new_test_ext().execute_with(|| { + // signed by an arbitrary non-root account → BadOrigin + assert_noop!( + ExternalValidators::set_external_validators(RuntimeOrigin::signed(1), vec![50, 51], 1), + BadOrigin + ); + + // unsigned → BadOrigin + assert_noop!( + ExternalValidators::set_external_validators(RuntimeOrigin::none(), vec![50, 51], 1), + BadOrigin + ); + + // root origin (requires signed(777) specifically, not sudo root) → BadOrigin + assert_noop!( + ExternalValidators::set_external_validators(RuntimeOrigin::root(), vec![50, 51], 1), + BadOrigin + ); + + // success with the correct signed origin + assert_ok!(ExternalValidators::set_external_validators( + RuntimeOrigin::signed(RootAccount::get()), + vec![50, 51], + 1 + )); + }); +} + +#[test] +fn target_era_validation_rejects_u64_max() { + new_test_ext().execute_with(|| { + // At genesis, active_era = 0; u64::MAX is far above active_era + 1 + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], u64::MAX), + Error::::TargetEraTooNew + ); + }); +} + +#[test] +fn era_boundary_race_submit_advance_resubmit() { + new_test_ext().execute_with(|| { + // At genesis (active_era = 0), submit for era 1 + assert_ok!(ExternalValidators::set_external_validators_inner( + vec![50, 51], + 1 + )); + + // Advance to era 1 (session 6 starts era 1) + run_to_session(6); + + // Re-submit for era 1 now that active_era = 1 → TargetEraTooOld + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 1), + Error::::TargetEraTooOld + ); + }); +} + +#[test] +fn era_boundary_race_resubmit_without_advance() { + new_test_ext().execute_with(|| { + // At genesis (active_era = 0), submit for era 1 + assert_ok!(ExternalValidators::set_external_validators_inner( + vec![50, 51], + 1 + )); + + // Immediately re-submit for era 1 without advancing → DuplicateOrStaleTargetEra + assert_noop!( + ExternalValidators::set_external_validators_inner(vec![50, 51], 1), + Error::::DuplicateOrStaleTargetEra + ); + }); +} diff --git a/operator/pallets/session-benchmarking/Cargo.toml b/operator/pallets/session-benchmarking/Cargo.toml new file mode 100644 index 00000000..41b64d87 --- /dev/null +++ b/operator/pallets/session-benchmarking/Cargo.toml @@ -0,0 +1,40 @@ +[package] +authors = { workspace = true } +description = "Benchmarking helpers for pallet-session in DataHaven runtimes." +edition = { workspace = true } +license = { workspace = true } +name = "pallet-session-benchmarking" +version = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lints] +workspace = true + +[dependencies] +codec = { workspace = true } +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +pallet-session = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "pallet-session/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/operator/pallets/session-benchmarking/src/benchmarking.rs b/operator/pallets/session-benchmarking/src/benchmarking.rs new file mode 100644 index 00000000..2b2f814a --- /dev/null +++ b/operator/pallets/session-benchmarking/src/benchmarking.rs @@ -0,0 +1,32 @@ +//! Benchmarks for solochain session usage (no staking dependency). +//! +//! This mirrors the upstream session benchmarks but avoids `pallet_staking` +//! by directly calling `pallet_session::Pallet::set_keys`. The session keys +//! are decoded from zeros, which works as long as the runtime wires Babe and +//! Grandpa into `SessionKeys`. + +use alloc::{vec, vec::Vec}; + +use codec::Decode; +use frame_benchmarking::{benchmarks, whitelisted_caller}; +use frame_system::RawOrigin; + +use crate::{Config, Pallet}; +use pallet_session::Call; + +benchmarks! { + set_keys { + let caller: T::AccountId = whitelisted_caller(); + frame_system::Pallet::::inc_providers(&caller); + let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap(); + let proof: Vec = vec![0, 1, 2, 3]; + }: _(RawOrigin::Signed(caller), keys, proof) + + purge_keys { + let caller: T::AccountId = whitelisted_caller(); + frame_system::Pallet::::inc_providers(&caller); + let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap(); + let proof: Vec = vec![0, 1, 2, 3]; + let _ = pallet_session::Pallet::::set_keys(RawOrigin::Signed(caller.clone()).into(), keys, proof); + }: _(RawOrigin::Signed(caller)) +} diff --git a/operator/pallets/session-benchmarking/src/lib.rs b/operator/pallets/session-benchmarking/src/lib.rs new file mode 100644 index 00000000..58849d81 --- /dev/null +++ b/operator/pallets/session-benchmarking/src/lib.rs @@ -0,0 +1,11 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +pub struct Pallet(pallet_session::Pallet); + +/// Benchmarking configuration for pallet-session in DataHaven. +pub trait Config: pallet_session::Config {} + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; diff --git a/operator/runtime/common/src/benchmarking.rs b/operator/runtime/common/src/benchmarking.rs index 746bdaf7..fabd218b 100644 --- a/operator/runtime/common/src/benchmarking.rs +++ b/operator/runtime/common/src/benchmarking.rs @@ -15,7 +15,9 @@ // along with Moonbeam. If not, see . use fp_account::AccountId20; +use frame_support::traits::Currency; use pallet_treasury::ArgumentsFactory; +use sp_runtime::traits::Zero; pub struct BenchmarkHelper; impl ArgumentsFactory<(), AccountId20> for BenchmarkHelper { @@ -31,3 +33,24 @@ impl ArgumentsFactory<(), AccountId20> for BenchmarkHelper { AccountId20::from(seed) } } + +pub struct StorageHubBenchmarking; +impl StorageHubBenchmarking { + pub const SP_MIN_DEPOSIT: u128 = 100_000_000_000_000; + pub const BUCKET_DEPOSIT: u128 = 100_000_000_000_000; + // Keep the benchmark challenge period within u32 limits. + pub const STAKE_TO_CHALLENGE_PERIOD: u128 = 3_000_000_000_000_000; + // Derived from StakeToChallengePeriod / SP_MIN_DEPOSIT + tolerance + 1. + pub const CHECKPOINT_CHALLENGE_PERIOD: u32 = 81; + + pub fn ensure_treasury_account(account: AccountId) -> AccountId + where + Balance: From + Zero, + CurrencyT: Currency, + { + if CurrencyT::free_balance(&account).is_zero() { + let _ = CurrencyT::deposit_creating(&account, 1u128.into()); + } + account + } +} diff --git a/operator/runtime/mainnet/Cargo.toml b/operator/runtime/mainnet/Cargo.toml index a7242a12..4de1517f 100644 --- a/operator/runtime/mainnet/Cargo.toml +++ b/operator/runtime/mainnet/Cargo.toml @@ -86,6 +86,7 @@ polkadot-runtime-common = { workspace = true } precompile-utils = { workspace = true } scale-info = { workspace = true, features = ["derive", "serde"] } serde = { workspace = true, features = ["derive"] } +k256 = { workspace = true, optional = true } serde_json = { workspace = true, default-features = false, features = [ "alloc", ] } @@ -360,6 +361,13 @@ runtime-benchmarks = [ "snowbridge-pallet-system/runtime-benchmarks", "pallet-outbound-commitment-store/runtime-benchmarks", "pallet-datahaven-native-transfer/runtime-benchmarks", + # StorageHub pallets + "pallet-nfts/runtime-benchmarks", + "pallet-file-system/runtime-benchmarks", + "pallet-proofs-dealer/runtime-benchmarks", + "pallet-payment-streams/runtime-benchmarks", + "pallet-storage-providers/runtime-benchmarks", + "dep:k256", ] try-runtime = [ diff --git a/operator/runtime/mainnet/src/benchmarks.rs b/operator/runtime/mainnet/src/benchmarks.rs index 48090e38..62136c7c 100644 --- a/operator/runtime/mainnet/src/benchmarks.rs +++ b/operator/runtime/mainnet/src/benchmarks.rs @@ -27,6 +27,7 @@ frame_benchmarking::define_benchmarks!( // Substrate pallets [pallet_balances, Balances] + [pallet_session, pallet_session_benchmarking::Pallet::] // FIXME: benchmarking identity fail // [pallet_identity, Identity] [pallet_im_online, ImOnline] @@ -47,6 +48,13 @@ frame_benchmarking::define_benchmarks!( // EVM pallets [pallet_evm, EVM] + // StorageHub pallets + [pallet_nfts, Nfts] + [pallet_file_system, FileSystem] + [pallet_proofs_dealer, ProofsDealer] + [pallet_payment_streams, PaymentStreams] + [pallet_storage_providers, Providers] + // Governance pallets [pallet_collective_technical_committee, TechnicalCommittee] [pallet_collective_treasury_council, TreasuryCouncil] diff --git a/operator/runtime/mainnet/src/configs/mod.rs b/operator/runtime/mainnet/src/configs/mod.rs index c65db6b7..fe152317 100644 --- a/operator/runtime/mainnet/src/configs/mod.rs +++ b/operator/runtime/mainnet/src/configs/mod.rs @@ -91,7 +91,6 @@ use datahaven_runtime_common::{ }, time::{EpochDurationInBlocks, SessionsPerEra, DAYS, MILLISECS_PER_BLOCK}, }; -use dhp_bridge::{EigenLayerMessageProcessor, NativeTokenTransferMessageProcessor}; use frame_support::{ derive_impl, dispatch::DispatchClass, @@ -126,7 +125,7 @@ use snowbridge_core::{gwei, meth, AgentIdOf, PricingParameters, Rewards, TokenId use snowbridge_inbound_queue_primitives::RewardLedger; use snowbridge_outbound_queue_primitives::{ v1::{Fee, Message, SendMessage}, - v2::{Command, ConstantGasMeter}, + v2::ConstantGasMeter, SendError, SendMessageFeeProvider, }; use snowbridge_pallet_outbound_queue_v2::OnNewCommitment; @@ -388,7 +387,7 @@ impl pallet_session::Config for Runtime { >; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - type WeightInfo = pallet_session::weights::SubstrateWeight; + type WeightInfo = mainnet_weights::pallet_session::WeightInfo; } parameter_types! { @@ -1108,47 +1107,13 @@ impl snowbridge_pallet_system_v2::Config for Runtime { type Helper = (); } -// Fork versions for runtime benchmarks - must match the fixtures for BLS verification to work -// The fixtures are generated with standard testnet fork versions -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub const ChainForkVersions: ForkVersions = ForkVersions { - genesis: Fork { - version: hex_literal::hex!("00000000"), - epoch: 0, - }, - altair: Fork { - version: hex_literal::hex!("01000000"), - epoch: 0, - }, - bellatrix: Fork { - version: hex_literal::hex!("02000000"), - epoch: 0, - }, - capella: Fork { - version: hex_literal::hex!("03000000"), - epoch: 0, - }, - deneb: Fork { - version: hex_literal::hex!("04000000"), - epoch: 0, - }, - electra: Fork { - version: hex_literal::hex!("05000000"), - epoch: 80000000000, - }, - fulu: Fork { - version: hex_literal::hex!("06000000"), - epoch: 90000000000, - }, - }; -} - // For tests, fast-runtime and std configurations we use the mocked fork versions // These match the fork versions used by the local Ethereum network in E2E tests -#[cfg(all( - any(feature = "std", feature = "fast-runtime", test), - not(feature = "runtime-benchmarks") +#[cfg(any( + feature = "std", + feature = "fast-runtime", + feature = "runtime-benchmarks", + test ))] parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { @@ -1278,8 +1243,8 @@ impl snowbridge_pallet_inbound_queue_v2::Config for Runtime { type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress; #[cfg(not(feature = "runtime-benchmarks"))] type MessageProcessor = ( - EigenLayerMessageProcessor, - NativeTokenTransferMessageProcessor, + dhp_bridge::EigenLayerMessageProcessor, + dhp_bridge::NativeTokenTransferMessageProcessor, ); #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = NoOpMessageProcessor; @@ -1750,6 +1715,7 @@ mod tests { use snowbridge_inbound_queue_primitives::v2::{ EthereumAsset, Message as SnowbridgeMessage, MessageProcessor, Payload as SnowPayload, }; + use snowbridge_outbound_queue_primitives::v2::Command; use sp_core::H160; use sp_io::TestExternalities; use xcm_builder::GlobalConsensusConvertsFor; @@ -1872,7 +1838,7 @@ mod tests { message_id: EL_MESSAGE_ID, message: BridgeMessage::V1(InboundCommand::ReceiveValidators { validators: Vec::new(), - external_index: 0, + external_index: 1, }), }; diff --git a/operator/runtime/mainnet/src/configs/runtime_params.rs b/operator/runtime/mainnet/src/configs/runtime_params.rs index d034192a..605c9f73 100644 --- a/operator/runtime/mainnet/src/configs/runtime_params.rs +++ b/operator/runtime/mainnet/src/configs/runtime_params.rs @@ -128,9 +128,9 @@ pub mod dynamic_params { /// /// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] ) /// - /// 500 = 50 + u * (e ^ (1 - 0.95) - 1) - /// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777 - pub static UpperExponentFactor: u32 = 8777; + /// 500 GIGAWEI = 50 GIGAWEI + u * (e ^ (1 - 0.95) - 1) + /// u = (500 GIGAWEI - 50 GIGAWEI) / (e ^ (1 - 0.95) - 1) ≈ 8,776,874,921,880 + pub static UpperExponentFactor: Balance = 8_776_874_921_880; #[codec(index = 15)] #[allow(non_upper_case_globals)] @@ -139,9 +139,9 @@ pub mod dynamic_params { /// /// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 ) /// - /// 10 = 50 - l * (e ^ (0.3 - 0) - 1) - /// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114 - pub static LowerExponentFactor: u32 = 114; + /// 10 GIGAWEI = 50 GIGAWEI - l * (e ^ (0.3 - 0) - 1) + /// l = (50 GIGAWEI - 10 GIGAWEI) / (e ^ (0.3 - 0) - 1) ≈ 114,331,836,540 + pub static LowerExponentFactor: Balance = 114_331_836_540; #[codec(index = 16)] #[allow(non_upper_case_globals)] diff --git a/operator/runtime/mainnet/src/configs/storagehub/mod.rs b/operator/runtime/mainnet/src/configs/storagehub/mod.rs index ca2f1d30..79a71b14 100644 --- a/operator/runtime/mainnet/src/configs/storagehub/mod.rs +++ b/operator/runtime/mainnet/src/configs/storagehub/mod.rs @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with DataHaven. If not, see . +#[cfg(not(feature = "runtime-benchmarks"))] +use super::HAVE; +#[cfg(feature = "runtime-benchmarks")] +use super::MICROHAVE; use super::{ AccountId, Balance, Balances, BlockNumber, Hash, RuntimeEvent, RuntimeHoldReason, - TreasuryAccount, HAVE, + TreasuryAccount, }; use crate::configs::runtime_params::dynamic_params::runtime_config; use crate::{ @@ -24,6 +28,8 @@ use crate::{ HOURS, }; use core::marker::PhantomData; +#[cfg(feature = "runtime-benchmarks")] +use datahaven_runtime_common::benchmarking::StorageHubBenchmarking; use datahaven_runtime_common::time::{DAYS, MINUTES}; use frame_support::pallet_prelude::DispatchClass; use frame_support::traits::AsEnsureOriginWithArg; @@ -33,7 +39,7 @@ use frame_support::{ weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use frame_system::{EnsureRoot, EnsureSigned}; +use frame_system::EnsureSigned; use num_bigint::BigUint; use pallet_nfts::PalletFeatures; use polkadot_runtime_common::prod_or_fast; @@ -68,6 +74,7 @@ pub type StorageProofsMerkleTrieLayout = LayoutV1; pub type Hashing = BlakeTwo256; /****** NFTs pallet ******/ +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const CollectionDeposit: Balance = 100 * HAVE; pub const ItemDeposit: Balance = 1 * HAVE; @@ -80,6 +87,19 @@ parameter_types! { pub const MaxAttributesPerCall: u32 = 10; pub Features: PalletFeatures = PalletFeatures::all_enabled(); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const CollectionDeposit: Balance = 100 * MICROHAVE; + pub const ItemDeposit: Balance = 1 * MICROHAVE; + pub const MetadataDepositBase: Balance = 10 * MICROHAVE; + pub const MetadataDepositPerByte: Balance = 1 * MICROHAVE; + pub const ApprovalsLimit: u32 = 20; + pub const ItemAttributesApprovalsLimit: u32 = 20; + pub const MaxTips: u32 = 10; + pub const MaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; + pub const MaxAttributesPerCall: u32 = 10; + pub Features: PalletFeatures = PalletFeatures::all_enabled(); +} impl pallet_nfts::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -104,11 +124,66 @@ impl pallet_nfts::Config for Runtime { type Features = Features; type OffchainSignature = Signature; type OffchainPublic = ::Signer; - type WeightInfo = pallet_nfts::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_nfts::WeightInfo; type Locker = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = benchmark_helpers::NftHelper; } /****** ****** ****** ******/ +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmark_helpers { + use crate::{AccountId, Signature}; + use k256::ecdsa::SigningKey; + use sp_runtime::traits::{IdentifyAccount, Verify}; + use sp_runtime::MultiSignature; + + const BENCH_SIGNING_KEY: [u8; 32] = [1u8; 32]; + + fn bench_signing_key() -> SigningKey { + SigningKey::from_bytes(&BENCH_SIGNING_KEY.into()) + .expect("benchmark signing key is valid; qed") + } + + /// Benchmark helper for NFTs pallet + pub struct NftHelper; + + impl pallet_nfts::BenchmarkHelper::Signer, AccountId, Signature> + for NftHelper + { + fn collection(i: u16) -> u32 { + i.into() + } + + fn item(i: u16) -> u32 { + i.into() + } + + fn signer() -> (::Signer, AccountId) { + let signing_key = bench_signing_key(); + let verifying_key = signing_key.verifying_key(); + let encoded = verifying_key.to_encoded_point(true); + let public = + sp_core::ecdsa::Public::from_full(encoded.as_bytes()).expect("valid key; qed"); + let public_key: ::Signer = public.into(); + let account: AccountId = public_key.clone().into_account(); + (public_key, account) + } + + fn sign(_public: &::Signer, message: &[u8]) -> Signature { + let digest = sp_io::hashing::keccak_256(message); + let (sig, recovery_id) = bench_signing_key() + .sign_prehash_recoverable(&digest) + .expect("signing with fixed key never fails; qed"); + let mut sig_bytes = [0u8; 65]; + sig_bytes[..64].copy_from_slice(&sig.to_bytes()); + sig_bytes[64] = recovery_id.to_byte(); + let sig = sp_core::ecdsa::Signature::from_raw(sig_bytes); + Signature::from(MultiSignature::Ecdsa(sig)) + } + } +} + /****** Relay Randomness pallet ******/ impl pallet_randomness::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -151,6 +226,7 @@ impl sp_runtime::traits::BlockNumberProvider for BlockNumberGetter { /****** ****** ****** ******/ /****** Storage Providers pallet ******/ +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const SpMinDeposit: Balance = 100 * HAVE; pub const BucketDeposit: Balance = 100 * HAVE; @@ -159,10 +235,47 @@ parameter_types! { // TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues) // pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const SpMinDeposit: Balance = StorageHubBenchmarking::SP_MIN_DEPOSIT; + pub const BucketDeposit: Balance = StorageHubBenchmarking::BUCKET_DEPOSIT; + pub const BspSignUpLockPeriod: BlockNumber = 90 * DAYS; // ~3 months + pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * HOURS, 2 * MINUTES); + // TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues) + // pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES); +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct StorageHubTreasuryAccount; +#[cfg(feature = "runtime-benchmarks")] +impl Get for StorageHubTreasuryAccount { + fn get() -> AccountId { + let account = TreasuryAccount::get(); + StorageHubBenchmarking::ensure_treasury_account::(account) + } +} + +// Benchmark helpers for Storage Providers pallet. +#[cfg(feature = "runtime-benchmarks")] +pub struct ProvidersBenchmarkHelpers; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_storage_providers::benchmarking::BenchmarkHelpers + for ProvidersBenchmarkHelpers +{ + type ProviderId = ::ProviderId; + + fn set_accrued_failed_proofs(provider_id: Self::ProviderId, value: u32) { + pallet_proofs_dealer::SlashableProviders::::insert(provider_id, value); + } + + fn get_accrued_failed_proofs(provider_id: Self::ProviderId) -> u32 { + pallet_proofs_dealer::SlashableProviders::::get(provider_id).unwrap_or(0) + } +} impl pallet_storage_providers::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_storage_providers::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_storage_providers::WeightInfo; type ProvidersRandomness = pallet_randomness::RandomnessFromOneEpochAgo; type PaymentStreams = PaymentStreams; type ProofDealer = ProofsDealer; @@ -188,7 +301,10 @@ impl pallet_storage_providers::Config for Runtime { type ProvidersProofSubmitters = ProofsDealer; type ReputationWeightType = u32; type StorageHubTickGetter = ProofsDealer; + #[cfg(not(feature = "runtime-benchmarks"))] type Treasury = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type Treasury = StorageHubTreasuryAccount; type SpMinDeposit = SpMinDeposit; type SpMinCapacity = ConstU64<2>; type DepositPerData = ConstU128<2>; @@ -208,6 +324,8 @@ impl pallet_storage_providers::Config for Runtime { type ZeroSizeBucketFixedRate = runtime_config::ZeroSizeBucketFixedRate; type ProviderTopUpTtl = runtime_config::ProviderTopUpTtl; type MaxExpiredItemsInBlock = ConstU32<100>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelpers = ProvidersBenchmarkHelpers; } pub struct StorageDataUnitAndBalanceConverter; @@ -240,7 +358,7 @@ parameter_types! { impl pallet_payment_streams::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_payment_streams::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_payment_streams::WeightInfo; type NativeBalance = Balances; type ProvidersPallet = Providers; type RuntimeHoldReason = RuntimeHoldReason; @@ -250,7 +368,10 @@ impl pallet_payment_streams::Config for Runtime { type BlockNumberToBalance = BlockNumberToBalance; type ProvidersProofSubmitters = ProofsDealer; type TreasuryCutCalculator = LinearThenPowerOfTwoTreasuryCutCalculator; + #[cfg(not(feature = "runtime-benchmarks"))] type TreasuryAccount = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type TreasuryAccount = StorageHubTreasuryAccount; type MaxUsersToCharge = ConstU32<10>; type BaseDeposit = ConstU128<10>; } @@ -279,6 +400,14 @@ const MAX_CUSTOM_CHALLENGES_PER_BLOCK: u32 = 10; const TOTAL_MAX_CHALLENGES_PER_BLOCK: u32 = RANDOM_CHALLENGES_PER_BLOCK + MAX_CUSTOM_CHALLENGES_PER_BLOCK; +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BenchmarkStakeToChallengePeriod: Balance = + StorageHubBenchmarking::STAKE_TO_CHALLENGE_PERIOD; + pub const BenchmarkCheckpointChallengePeriod: BlockNumber = + StorageHubBenchmarking::CHECKPOINT_CHALLENGE_PERIOD; +} + parameter_types! { pub const RandomChallengesPerBlock: u32 = RANDOM_CHALLENGES_PER_BLOCK; pub const MaxCustomChallengesPerBlock: u32 = MAX_CUSTOM_CHALLENGES_PER_BLOCK; @@ -293,7 +422,7 @@ parameter_types! { impl pallet_proofs_dealer::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_proofs_dealer::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_proofs_dealer::WeightInfo; type ProvidersPallet = Providers; type NativeBalance = Balances; type MerkleTrieHash = Hash; @@ -306,29 +435,50 @@ impl pallet_proofs_dealer::Config for Runtime { { shp_constants::FILE_SIZE_TO_CHALLENGES }, >; type StakeToBlockNumber = SaturatingBalanceToBlockNumber; + #[cfg(feature = "runtime-benchmarks")] + type RandomChallengesPerBlock = ConstU32<0>; + #[cfg(not(feature = "runtime-benchmarks"))] type RandomChallengesPerBlock = RandomChallengesPerBlock; + #[cfg(feature = "runtime-benchmarks")] + type MaxCustomChallengesPerBlock = TotalMaxChallengesPerBlock; + #[cfg(not(feature = "runtime-benchmarks"))] type MaxCustomChallengesPerBlock = MaxCustomChallengesPerBlock; type MaxSubmittersPerTick = MaxSubmittersPerTick; type TargetTicksStorageOfSubmitters = TargetTicksStorageOfSubmitters; type ChallengeHistoryLength = ChallengeHistoryLength; type ChallengesQueueLength = ChallengesQueueLength; + #[cfg(not(feature = "runtime-benchmarks"))] type CheckpointChallengePeriod = runtime_config::CheckpointChallengePeriod; + #[cfg(feature = "runtime-benchmarks")] + type CheckpointChallengePeriod = BenchmarkCheckpointChallengePeriod; type ChallengesFee = ChallengesFee; type PriorityChallengesFee = PriorityChallengesFee; + #[cfg(not(feature = "runtime-benchmarks"))] type Treasury = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type Treasury = StorageHubTreasuryAccount; // TODO: Once the client logic to keep track of CR randomness deadlines and execute their submissions is implemented // AND after the chain has been live for enough time to have enough providers to avoid the commit-reveal randomness being // gameable, the randomness provider should be CrRandomness type RandomnessProvider = pallet_randomness::ParentBlockRandomness; + #[cfg(not(feature = "runtime-benchmarks"))] type StakeToChallengePeriod = runtime_config::StakeToChallengePeriod; + #[cfg(feature = "runtime-benchmarks")] + type StakeToChallengePeriod = BenchmarkStakeToChallengePeriod; type MinChallengePeriod = runtime_config::MinChallengePeriod; type ChallengeTicksTolerance = ChallengeTicksTolerance; type BlockFullnessPeriod = ChallengeTicksTolerance; // We purposely set this to `ChallengeTicksTolerance` so that spamming of the chain is evaluated for the same blocks as the tolerance BSPs are given. type BlockFullnessHeadroom = BlockFullnessHeadroom; type MinNotFullBlocksRatio = MinNotFullBlocksRatio; type MaxSlashableProvidersPerTick = MaxSlashableProvidersPerTick; - type ChallengeOrigin = EnsureRoot; - type PriorityChallengeOrigin = EnsureRoot; + #[cfg(not(feature = "runtime-benchmarks"))] + type ChallengeOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ChallengeOrigin = EnsureSigned; + #[cfg(not(feature = "runtime-benchmarks"))] + type PriorityChallengeOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type PriorityChallengeOrigin = EnsureSigned; } // Converter from the Balance type to the BlockNumber type for math. @@ -452,12 +602,24 @@ impl Get for MaxSlashableProvidersPerTick { type ThresholdType = u32; pub type ReplicationTargetType = u32; +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const BaseStorageRequestCreationDeposit: Balance = 1 * HAVE; pub const FileDeletionRequestCreationDeposit: Balance = 1 * HAVE; pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold); pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BaseStorageRequestCreationDeposit: Balance = 1 * MICROHAVE; + pub const FileDeletionRequestCreationDeposit: Balance = 1 * MICROHAVE; + pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold); + pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold); +} +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BenchmarkBspStopStoringFilePenalty: Balance = 1 * MICROHAVE; +} // Converts a given signed message in a EIP-191 compliant message bytes to verify. /// EIP-191: https://eips.ethereum.org/EIPS/eip-191 @@ -480,7 +642,7 @@ impl shp_traits::MessageAdapter for Eip191Adapter { impl pallet_file_system::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_file_system::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_file_system::WeightInfo; type Providers = Providers; type ProofDealer = ProofsDealer; type PaymentStreams = PaymentStreams; @@ -500,8 +662,14 @@ impl pallet_file_system::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type Nfts = Nfts; type CollectionInspector = BucketNfts; + #[cfg(not(feature = "runtime-benchmarks"))] type BspStopStoringFilePenalty = runtime_config::BspStopStoringFilePenalty; + #[cfg(feature = "runtime-benchmarks")] + type BspStopStoringFilePenalty = BenchmarkBspStopStoringFilePenalty; + #[cfg(not(feature = "runtime-benchmarks"))] type TreasuryAccount = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type TreasuryAccount = StorageHubTreasuryAccount; type MaxBatchConfirmStorageRequests = ConstU32<100>; type MaxFilePathSize = ConstU32<512u32>; type MaxPeerIdSize = ConstU32<100>; diff --git a/operator/runtime/mainnet/src/genesis_config_presets.rs b/operator/runtime/mainnet/src/genesis_config_presets.rs index 15e9d2da..321df0a1 100644 --- a/operator/runtime/mainnet/src/genesis_config_presets.rs +++ b/operator/runtime/mainnet/src/genesis_config_presets.rs @@ -258,7 +258,7 @@ pub fn dorothy() -> AccountId { } pub fn ethan() -> AccountId { - AccountId::from(hex!("Ff64d3F6efE2317EE2807d2235B1ac2AA69d9E87")) + AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")) } pub fn frank() -> AccountId { diff --git a/operator/runtime/mainnet/src/lib.rs b/operator/runtime/mainnet/src/lib.rs index d27f07e2..660a630e 100644 --- a/operator/runtime/mainnet/src/lib.rs +++ b/operator/runtime/mainnet/src/lib.rs @@ -142,7 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 1000, + spec_version: 1300, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -201,7 +201,7 @@ parameter_types! { parameter_types! { // TODO: Change ED to 1 after upgrade to Polkadot SDK stable2503 // cfr. https://github.com/paritytech/polkadot-sdk/pull/7379 - pub const ExistentialDeposit: Balance = 100; + pub const ExistentialDeposit: Balance = 1; } /// The version information used to identify this runtime when compiled natively. @@ -972,6 +972,7 @@ impl_runtime_apis! { use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} + impl pallet_session_benchmarking::Config for Runtime {} impl baseline::Config for Runtime {} use frame_support::traits::WhitelistedStorageKeys; @@ -1263,6 +1264,9 @@ impl_runtime_apis! { ) -> Vec { FileSystem::query_pending_bsp_confirm_storage_requests(bsp_id, file_keys) } + fn get_max_batch_confirm_storage_requests() -> BlockNumber { + FileSystem::get_max_batch_confirm_storage_requests() + } } impl pallet_payment_streams_runtime_api::PaymentStreamsApi, Balance, AccountId> for Runtime { diff --git a/operator/runtime/mainnet/src/weights/mod.rs b/operator/runtime/mainnet/src/weights/mod.rs index 1ff1a426..4a92b29b 100644 --- a/operator/runtime/mainnet/src/weights/mod.rs +++ b/operator/runtime/mainnet/src/weights/mod.rs @@ -35,18 +35,24 @@ pub mod pallet_babe; pub mod pallet_balances; pub mod pallet_beefy_mmr; pub mod pallet_evm; +pub mod pallet_file_system; pub mod pallet_grandpa; pub mod pallet_im_online; pub mod pallet_message_queue; pub mod pallet_migrations; pub mod pallet_mmr; pub mod pallet_multisig; +pub mod pallet_nfts; pub mod pallet_parameters; +pub mod pallet_payment_streams; pub mod pallet_preimage; +pub mod pallet_proofs_dealer; pub mod pallet_proxy; pub mod pallet_randomness; pub mod pallet_safe_mode; pub mod pallet_scheduler; +pub mod pallet_session; +pub mod pallet_storage_providers; pub mod pallet_sudo; pub mod pallet_timestamp; pub mod pallet_transaction_payment; diff --git a/operator/runtime/mainnet/src/weights/pallet_file_system.rs b/operator/runtime/mainnet/src/weights/pallet_file_system.rs new file mode 100644 index 00000000..4a2a2050 --- /dev/null +++ b/operator/runtime/mainnet/src/weights/pallet_file_system.rs @@ -0,0 +1,5 @@ +//! Weights for `pallet_file_system`. +//! +//! Generated weights should overwrite this file. + +pub use pallet_file_system::weights::SubstrateWeight as WeightInfo; diff --git a/operator/runtime/mainnet/src/weights/pallet_nfts.rs b/operator/runtime/mainnet/src/weights/pallet_nfts.rs new file mode 100644 index 00000000..4ffc4faf --- /dev/null +++ b/operator/runtime/mainnet/src/weights/pallet_nfts.rs @@ -0,0 +1,726 @@ + + +//! Autogenerated weights for `pallet_nfts` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2025-11-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-mainnet-runtime/datahaven_mainnet_runtime.compact.compressed.wasm +// --pallet +// pallet_nfts +// --extrinsic +// +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/mainnet/src/weights/pallet_nfts.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_nfts`. +pub struct WeightInfo(PhantomData); +impl pallet_nfts::WeightInfo for WeightInfo { + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `271` + // Estimated: `3537` + // Minimum execution time: 46_980_000 picoseconds. + Weight::from_parts(48_333_000, 3537) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn force_create() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3537` + // Minimum execution time: 25_388_000 picoseconds. + Weight::from_parts(26_185_000, 3537) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// The range of component `m` is `[0, 1000]`. + /// The range of component `c` is `[0, 1000]`. + /// The range of component `a` is `[0, 1000]`. + fn destroy(m: u32, _c: u32, a: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `32179 + a * (366 ±0)` + // Estimated: `2523990 + a * (2930 ±0)` + // Minimum execution time: 1_376_605_000 picoseconds. + Weight::from_parts(1_488_155_322, 2523990) + // Standard Error: 20_663 + .saturating_add(Weight::from_parts(65_636, 0).saturating_mul(m.into())) + // Standard Error: 20_663 + .saturating_add(Weight::from_parts(8_224_542, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1004_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) + .saturating_add(T::DbWeight::get().writes(1005_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(a.into())) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + fn mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `418` + // Estimated: `4062` + // Minimum execution time: 67_377_000 picoseconds. + Weight::from_parts(68_962_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + fn force_mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `418` + // Estimated: `4062` + // Minimum execution time: 65_493_000 picoseconds. + Weight::from_parts(67_405_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn burn() -> Weight { + // Proof Size summary in bytes: + // Measured: `526` + // Estimated: `4062` + // Minimum execution time: 73_291_000 picoseconds. + Weight::from_parts(75_035_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `555` + // Estimated: `4062` + // Minimum execution time: 56_413_000 picoseconds. + Weight::from_parts(58_224_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:5000 w:5000) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 5000]`. + fn redeposit(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `750 + i * (83 ±0)` + // Estimated: `3538 + i * (3072 ±0)` + // Minimum execution time: 18_658_000 picoseconds. + Weight::from_parts(19_263_000, 3538) + // Standard Error: 28_107 + .saturating_add(Weight::from_parts(24_930_095, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) + .saturating_add(Weight::from_parts(0, 3072).saturating_mul(i.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn lock_item_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 24_194_000 picoseconds. + Weight::from_parts(25_183_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn unlock_item_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 24_302_000 picoseconds. + Weight::from_parts(24_760_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn lock_collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `327` + // Estimated: `3538` + // Minimum execution time: 20_173_000 picoseconds. + Weight::from_parts(20_850_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn transfer_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `524` + // Estimated: `3581` + // Minimum execution time: 35_232_000 picoseconds. + Weight::from_parts(36_300_000, 3581) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + fn set_team() -> Weight { + // Proof Size summary in bytes: + // Measured: `344` + // Estimated: `6054` + // Minimum execution time: 49_520_000 picoseconds. + Weight::from_parts(50_640_000, 6054) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn force_collection_owner() -> Weight { + // Proof Size summary in bytes: + // Measured: `298` + // Estimated: `3537` + // Minimum execution time: 20_820_000 picoseconds. + Weight::from_parts(21_202_000, 3537) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn force_collection_config() -> Weight { + // Proof Size summary in bytes: + // Measured: `276` + // Estimated: `3537` + // Minimum execution time: 16_693_000 picoseconds. + Weight::from_parts(17_330_000, 3537) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn lock_item_properties() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 23_027_000 picoseconds. + Weight::from_parts(23_442_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + fn set_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `514` + // Estimated: `3920` + // Minimum execution time: 68_689_000 picoseconds. + Weight::from_parts(70_511_000, 3920) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + fn force_set_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `331` + // Estimated: `3920` + // Minimum execution time: 32_782_000 picoseconds. + Weight::from_parts(33_772_000, 3920) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + fn clear_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `958` + // Estimated: `3920` + // Minimum execution time: 62_968_000 picoseconds. + Weight::from_parts(64_747_000, 3920) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + fn approve_item_attributes() -> Weight { + // Proof Size summary in bytes: + // Measured: `356` + // Estimated: `4062` + // Minimum execution time: 20_730_000 picoseconds. + Weight::from_parts(21_384_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn cancel_item_attributes_approval(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `769 + n * (386 ±0)` + // Estimated: `4062 + n * (2930 ±0)` + // Minimum execution time: 33_379_000 picoseconds. + Weight::from_parts(34_195_000, 4062) + // Standard Error: 4_787 + .saturating_add(Weight::from_parts(7_772_947, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + fn set_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `514` + // Estimated: `3800` + // Minimum execution time: 56_022_000 picoseconds. + Weight::from_parts(57_731_000, 3800) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn clear_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `824` + // Estimated: `3800` + // Minimum execution time: 53_756_000 picoseconds. + Weight::from_parts(54_834_000, 3800) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + fn set_collection_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `373` + // Estimated: `3759` + // Minimum execution time: 50_526_000 picoseconds. + Weight::from_parts(52_262_000, 3759) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + fn clear_collection_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `691` + // Estimated: `3759` + // Minimum execution time: 50_577_000 picoseconds. + Weight::from_parts(51_516_000, 3759) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn approve_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `385` + // Estimated: `4062` + // Minimum execution time: 24_204_000 picoseconds. + Weight::from_parts(25_158_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn cancel_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `4062` + // Minimum execution time: 21_067_000 picoseconds. + Weight::from_parts(21_663_000, 4062) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn clear_all_transfer_approvals() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `4062` + // Minimum execution time: 19_982_000 picoseconds. + Weight::from_parts(20_493_000, 4062) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn set_accept_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3505` + // Minimum execution time: 17_144_000 picoseconds. + Weight::from_parts(17_739_000, 3505) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + fn set_collection_max_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `327` + // Estimated: `3538` + // Minimum execution time: 22_173_000 picoseconds. + Weight::from_parts(22_774_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn update_mint_settings() -> Weight { + // Proof Size summary in bytes: + // Measured: `311` + // Estimated: `3538` + // Minimum execution time: 21_245_000 picoseconds. + Weight::from_parts(21_957_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + fn set_price() -> Weight { + // Proof Size summary in bytes: + // Measured: `493` + // Estimated: `4062` + // Minimum execution time: 30_559_000 picoseconds. + Weight::from_parts(31_877_000, 4062) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn buy_item() -> Weight { + // Proof Size summary in bytes: + // Measured: `655` + // Estimated: `4062` + // Minimum execution time: 66_567_000 picoseconds. + Weight::from_parts(68_264_000, 4062) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// The range of component `n` is `[0, 10]`. + fn pay_tips(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_221_000 picoseconds. + Weight::from_parts(4_654_516, 0) + // Standard Error: 7_679 + .saturating_add(Weight::from_parts(2_619_134, 0).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:2 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn create_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `444` + // Estimated: `7134` + // Minimum execution time: 26_849_000 picoseconds. + Weight::from_parts(27_644_000, 7134) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn cancel_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `488` + // Estimated: `4062` + // Minimum execution time: 27_431_000 picoseconds. + Weight::from_parts(27_897_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:2 w:2) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:2 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:4) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + fn claim_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `771` + // Estimated: `7134` + // Minimum execution time: 110_387_000 picoseconds. + Weight::from_parts(112_526_000, 7134) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(10_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn mint_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `580` + // Estimated: `6054 + n * (2930 ±0)` + // Minimum execution time: 159_612_000 picoseconds. + Weight::from_parts(166_084_283, 6054) + // Standard Error: 67_116 + .saturating_add(Weight::from_parts(43_826_364, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn set_attributes_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `575` + // Estimated: `4062 + n * (2930 ±0)` + // Minimum execution time: 75_695_000 picoseconds. + Weight::from_parts(89_915_935, 4062) + // Standard Error: 98_709 + .saturating_add(Weight::from_parts(42_240_220, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } +} diff --git a/operator/runtime/mainnet/src/weights/pallet_payment_streams.rs b/operator/runtime/mainnet/src/weights/pallet_payment_streams.rs new file mode 100644 index 00000000..3022e4da --- /dev/null +++ b/operator/runtime/mainnet/src/weights/pallet_payment_streams.rs @@ -0,0 +1,449 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_payment_streams` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-mainnet-runtime/datahaven_mainnet_runtime.compact.compressed.wasm +// --pallet +// pallet_payment_streams +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/mainnet/src/weights/pallet_payment_streams.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_payment_streams`. +pub struct WeightInfo(PhantomData); +impl pallet_payment_streams::weights::WeightInfo for WeightInfo { + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn create_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `523` + // Estimated: `6054` + // Minimum execution time: 107_606_000 picoseconds. + Weight::from_parts(108_915_000, 6054) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn update_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1427` + // Estimated: `12414` + // Minimum execution time: 403_134_000 picoseconds. + Weight::from_parts(416_206_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn delete_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1304` + // Estimated: `12414` + // Minimum execution time: 295_969_000 picoseconds. + Weight::from_parts(300_145_000, 12414) + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:0) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn create_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `525` + // Estimated: `6054` + // Minimum execution time: 110_904_000 picoseconds. + Weight::from_parts(113_365_000, 6054) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn update_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1387` + // Estimated: `12414` + // Minimum execution time: 351_490_000 picoseconds. + Weight::from_parts(354_309_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn delete_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1455` + // Estimated: `12414` + // Minimum execution time: 399_760_000 picoseconds. + Weight::from_parts(410_315_000, 12414) + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn charge_payment_streams() -> Weight { + // Proof Size summary in bytes: + // Measured: `1441` + // Estimated: `12414` + // Minimum execution time: 335_054_000 picoseconds. + Weight::from_parts(339_893_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:10 w:10) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:10 w:10) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:10 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:12 w:12) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn charge_multiple_users_payment_streams(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1122 + n * (331 ±0)` + // Estimated: `12414 + n * (2604 ±0)` + // Minimum execution time: 20_587_000 picoseconds. + Weight::from_parts(44_190_125, 12414) + // Standard Error: 170_219 + .saturating_add(Weight::from_parts(294_748_615, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2604).saturating_mul(n.into())) + } + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1001 w:1001) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:999 w:999) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:999 w:999) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:999 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:999 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:999 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn pay_outstanding_debt(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1422 + n * (644 ±0)` + // Estimated: `12414 + n * (3634 ±0)` + // Minimum execution time: 376_066_000 picoseconds. + Weight::from_parts(378_172_000, 12414) + // Standard Error: 147_940 + .saturating_add(Weight::from_parts(283_749_757, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3634).saturating_mul(n.into())) + } + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:1) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:0) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn clear_insolvent_flag() -> Weight { + // Proof Size summary in bytes: + // Measured: `231` + // Estimated: `3505` + // Minimum execution time: 22_472_000 picoseconds. + Weight::from_parts(23_180_000, 3505) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:1) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn price_index_update() -> Weight { + // Proof Size summary in bytes: + // Measured: `116` + // Estimated: `1501` + // Minimum execution time: 5_847_000 picoseconds. + Weight::from_parts(6_187_000, 1501) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:1) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn tick_update() -> Weight { + // Proof Size summary in bytes: + // Measured: `114` + // Estimated: `1489` + // Minimum execution time: 3_884_000 picoseconds. + Weight::from_parts(4_063_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastSubmittersTickRegistered` (r:1 w:1) + /// Proof: `PaymentStreams::LastSubmittersTickRegistered` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:0) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:0) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:244 w:244) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 244]`. + fn update_providers_last_chargeable_info(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `270 + n * (32 ±0)` + // Estimated: `11295 + n * (2543 ±0)` + // Minimum execution time: 12_468_000 picoseconds. + Weight::from_parts(9_805_506, 11295) + // Standard Error: 5_017 + .saturating_add(Weight::from_parts(6_952_512, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2543).saturating_mul(n.into())) + } +} diff --git a/operator/runtime/mainnet/src/weights/pallet_proofs_dealer.rs b/operator/runtime/mainnet/src/weights/pallet_proofs_dealer.rs new file mode 100644 index 00000000..1d9541c8 --- /dev/null +++ b/operator/runtime/mainnet/src/weights/pallet_proofs_dealer.rs @@ -0,0 +1,326 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_proofs_dealer` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-mainnet-runtime/datahaven_mainnet_runtime.compact.compressed.wasm +// --pallet +// pallet_proofs_dealer +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/mainnet/src/weights/pallet_proofs_dealer.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_proofs_dealer`. +pub struct WeightInfo(PhantomData); +impl pallet_proofs_dealer::weights::WeightInfo for WeightInfo { + /// Storage: `ProofsDealer::ChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + fn challenge() -> Weight { + // Proof Size summary in bytes: + // Measured: `41` + // Estimated: `4687` + // Minimum execution time: 11_710_000 picoseconds. + Weight::from_parts(12_273_000, 4687) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:2 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:1 w:0) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:5 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:2) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 20]`. + fn submit_proof_no_checkpoint_challenges_key_proofs(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2070` + // Estimated: `15270` + // Minimum execution time: 2_180_337_000 picoseconds. + Weight::from_parts(2_068_089_120, 15270) + // Standard Error: 256_975 + .saturating_add(Weight::from_parts(139_273_283, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(30_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:1 w:0) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:2) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// The range of component `n` is `[21, 40]`. + fn submit_proof_with_checkpoint_challenges_key_proofs(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2070` + // Estimated: `20676` + // Minimum execution time: 4_705_521_000 picoseconds. + Weight::from_parts(4_096_774_230, 20676) + // Standard Error: 968_637 + .saturating_add(Weight::from_parts(38_494_397, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(39_u64)) + .saturating_add(T::DbWeight::get().writes(11_u64)) + } + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestParentBlockRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestParentBlockRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckForSlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::TickToCheckForSlashableProviders` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:1001 w:2000) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1000 w:1000) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1000 w:1000) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1000 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1000 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:0 w:1) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn new_challenges_round(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1155 + n * (271 ±0)` + // Estimated: `6172 + n * (3634 ±0)` + // Minimum execution time: 29_450_000 picoseconds. + Weight::from_parts(30_176_000, 6172) + // Standard Error: 45_927 + .saturating_add(Weight::from_parts(40_350_233, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3634).saturating_mul(n.into())) + } + /// Storage: `ProofsDealer::PriorityChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::PriorityChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:1) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:0 w:2) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 20]`. + fn new_checkpoint_challenge_round(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `65 + n * (32 ±0)` + // Estimated: `4787` + // Minimum execution time: 14_001_000 picoseconds. + Weight::from_parts(15_995_280, 4787) + // Standard Error: 3_445 + .saturating_add(Weight::from_parts(449_577, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `ProofsDealer::PastBlocksStatus` (r:1 w:1) + /// Proof: `ProofsDealer::PastBlocksStatus` (`max_values`: Some(1), `max_size`: Some(51), added: 546, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::PastBlocksWeight` (r:1 w:0) + /// Proof: `ProofsDealer::PastBlocksWeight` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTickerPaused` (r:0 w:1) + /// Proof: `ProofsDealer::ChallengesTickerPaused` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `MaxEncodedLen`) + fn check_spamming_condition() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `3501` + // Minimum execution time: 14_141_000 picoseconds. + Weight::from_parts(14_450_000, 3501) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::LastDeletedTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastDeletedTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn trim_valid_proof_submitters_last_ticks_constant_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `41` + // Estimated: `1489` + // Minimum execution time: 4_433_000 picoseconds. + Weight::from_parts(4_657_000, 1489) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `ProofsDealer::LastDeletedTick` (r:0 w:1) + /// Proof: `ProofsDealer::LastDeletedTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:0 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + fn trim_valid_proof_submitters_last_ticks_loop() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_533_000 picoseconds. + Weight::from_parts(2_701_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::PastBlocksWeight` (r:0 w:2) + /// Proof: `ProofsDealer::PastBlocksWeight` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + fn on_finalize() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_812_000 picoseconds. + Weight::from_parts(5_079_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn force_initialise_challenge_cycle() -> Weight { + // Proof Size summary in bytes: + // Measured: `552` + // Estimated: `4624` + // Minimum execution time: 44_569_000 picoseconds. + Weight::from_parts(46_326_000, 4624) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::ChallengesTickerPaused` (r:0 w:1) + /// Proof: `ProofsDealer::ChallengesTickerPaused` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `MaxEncodedLen`) + fn set_paused() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_440_000 picoseconds. + Weight::from_parts(7_760_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} diff --git a/operator/runtime/mainnet/src/weights/pallet_session.rs b/operator/runtime/mainnet/src/weights/pallet_session.rs new file mode 100644 index 00000000..19df1fa9 --- /dev/null +++ b/operator/runtime/mainnet/src/weights/pallet_session.rs @@ -0,0 +1,84 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_session` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-mainnet-runtime/datahaven_mainnet_runtime.compact.compressed.wasm +// --pallet +// pallet_session +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/mainnet/src/weights/pallet_session.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_session`. +pub struct WeightInfo(PhantomData); +impl pallet_session::WeightInfo for WeightInfo { + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:4 w:4) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `350` + // Estimated: `11240` + // Minimum execution time: 36_482_000 picoseconds. + Weight::from_parts(37_467_000, 11240) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:0 w:4) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn purge_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 21_767_000 picoseconds. + Weight::from_parts(22_530_000, 3793) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } +} diff --git a/operator/runtime/mainnet/src/weights/pallet_storage_providers.rs b/operator/runtime/mainnet/src/weights/pallet_storage_providers.rs new file mode 100644 index 00000000..7ec61ac9 --- /dev/null +++ b/operator/runtime/mainnet/src/weights/pallet_storage_providers.rs @@ -0,0 +1,630 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_storage_providers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-mainnet-runtime/datahaven_mainnet_runtime.compact.compressed.wasm +// --pallet +// pallet_storage_providers +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/mainnet/src/weights/pallet_storage_providers.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_storage_providers`. +pub struct WeightInfo(PhantomData); +impl pallet_storage_providers::weights::WeightInfo for WeightInfo { + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn request_msp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 87_582_000 picoseconds. + Weight::from_parts(89_898_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn request_bsp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 88_155_000 picoseconds. + Weight::from_parts(90_220_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestOneEpochAgoRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestOneEpochAgoRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:0 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn confirm_sign_up_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `474` + // Estimated: `5628` + // Minimum execution time: 38_210_000 picoseconds. + Weight::from_parts(39_338_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestOneEpochAgoRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestOneEpochAgoRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:0 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn confirm_sign_up_msp() -> Weight { + // Proof Size summary in bytes: + // Measured: `487` + // Estimated: `5628` + // Minimum execution time: 54_698_000 picoseconds. + Weight::from_parts(55_937_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn cancel_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `507` + // Estimated: `5628` + // Minimum execution time: 65_127_000 picoseconds. + Weight::from_parts(65_875_000, 5628) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:102 w:101) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 100]`. + fn msp_sign_off(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `775 + n * (83 ±0)` + // Estimated: `8186 + n * (3598 ±0)` + // Minimum execution time: 91_582_000 picoseconds. + Weight::from_parts(91_148_393, 8186) + // Standard Error: 9_568 + .saturating_add(Weight::from_parts(6_388_975, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3598).saturating_mul(n.into())) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:0) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn bsp_sign_off() -> Weight { + // Proof Size summary in bytes: + // Measured: `720` + // Estimated: `4624` + // Minimum execution time: 92_255_000 picoseconds. + Weight::from_parts(93_446_000, 4624) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn change_capacity_bsp_less_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `679` + // Estimated: `4624` + // Minimum execution time: 82_856_000 picoseconds. + Weight::from_parts(85_018_000, 4624) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn change_capacity_bsp_more_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `679` + // Estimated: `4624` + // Minimum execution time: 102_474_000 picoseconds. + Weight::from_parts(104_618_000, 4624) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn change_capacity_msp_less_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `649` + // Estimated: `4608` + // Minimum execution time: 78_146_000 picoseconds. + Weight::from_parts(80_013_000, 4608) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn change_capacity_msp_more_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `649` + // Estimated: `4608` + // Minimum execution time: 97_535_000 picoseconds. + Weight::from_parts(99_407_000, 4608) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + fn add_value_prop() -> Weight { + // Proof Size summary in bytes: + // Measured: `591` + // Estimated: `4608` + // Minimum execution time: 45_319_000 picoseconds. + Weight::from_parts(46_335_000, 4608) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + fn make_value_prop_unavailable() -> Weight { + // Proof Size summary in bytes: + // Measured: `631` + // Estimated: `4608` + // Minimum execution time: 32_867_000 picoseconds. + Weight::from_parts(33_943_000, 4608) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn add_multiaddress() -> Weight { + // Proof Size summary in bytes: + // Measured: `508` + // Estimated: `4624` + // Minimum execution time: 34_149_000 picoseconds. + Weight::from_parts(35_552_000, 4624) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn remove_multiaddress() -> Weight { + // Proof Size summary in bytes: + // Measured: `1316` + // Estimated: `4624` + // Minimum execution time: 32_650_000 picoseconds. + Weight::from_parts(33_556_000, 4624) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:0 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn force_msp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 126_083_000 picoseconds. + Weight::from_parts(127_714_000, 5628) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:0 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn force_bsp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 104_033_000 picoseconds. + Weight::from_parts(106_787_000, 5628) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + fn slash_without_awaiting_top_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `871` + // Estimated: `6172` + // Minimum execution time: 159_588_000 picoseconds. + Weight::from_parts(161_719_000, 6172) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::NextAvailableProviderTopUpExpirationShTick` (r:1 w:1) + /// Proof: `Providers::NextAvailableProviderTopUpExpirationShTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::ProviderTopUpExpirations` (r:1 w:1) + /// Proof: `Providers::ProviderTopUpExpirations` (`max_values`: None, `max_size`: Some(3322), added: 5797, mode: `MaxEncodedLen`) + fn slash_with_awaiting_top_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `871` + // Estimated: `6787` + // Minimum execution time: 126_797_000 picoseconds. + Weight::from_parts(129_937_000, 6787) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::ProviderTopUpExpirations` (r:0 w:1) + /// Proof: `Providers::ProviderTopUpExpirations` (`max_values`: None, `max_size`: Some(3322), added: 5797, mode: `MaxEncodedLen`) + fn top_up_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `758` + // Estimated: `4624` + // Minimum execution time: 111_138_000 picoseconds. + Weight::from_parts(113_128_000, 4624) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::InsolventProviders` (r:2 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn delete_provider_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `853` + // Estimated: `6038` + // Minimum execution time: 80_884_000 picoseconds. + Weight::from_parts(82_175_000, 6038) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) + } + /// Storage: `Providers::InsolventProviders` (r:1 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:22 w:21) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToBuckets` (r:21 w:20) + /// Proof: `Providers::MainStorageProviderIdsToBuckets` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 20]`. + /// The range of component `m` is `[0, 20]`. + fn delete_provider_msp(n: u32, m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1845 + m * (54 ±0) + n * (83 ±0)` + // Estimated: `8186 + m * (2571 ±0) + n * (3598 ±0)` + // Minimum execution time: 184_840_000 picoseconds. + Weight::from_parts(79_815_534, 8186) + // Standard Error: 30_345 + .saturating_add(Weight::from_parts(6_847_952, 0).saturating_mul(n.into())) + // Standard Error: 30_345 + .saturating_add(Weight::from_parts(5_652_904, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) + .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(m.into()))) + .saturating_add(Weight::from_parts(0, 2571).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 3598).saturating_mul(n.into())) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:0) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn stop_all_cycles() -> Weight { + // Proof Size summary in bytes: + // Measured: `549` + // Estimated: `4624` + // Minimum execution time: 27_400_000 picoseconds. + Weight::from_parts(27_944_000, 4624) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:0 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn process_expired_provider_top_up_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `1038` + // Estimated: `6172` + // Minimum execution time: 103_682_000 picoseconds. + Weight::from_parts(105_525_000, 6172) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:0 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + fn process_expired_provider_top_up_msp() -> Weight { + // Proof Size summary in bytes: + // Measured: `775` + // Estimated: `6172` + // Minimum execution time: 83_347_000 picoseconds. + Weight::from_parts(84_976_000, 6172) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } +} diff --git a/operator/runtime/stagenet/Cargo.toml b/operator/runtime/stagenet/Cargo.toml index 131083a9..c1b33c46 100644 --- a/operator/runtime/stagenet/Cargo.toml +++ b/operator/runtime/stagenet/Cargo.toml @@ -86,6 +86,7 @@ polkadot-runtime-common = { workspace = true } precompile-utils = { workspace = true } scale-info = { workspace = true, features = ["derive", "serde"] } serde = { workspace = true, features = ["derive"] } +k256 = { workspace = true, optional = true } serde_json = { workspace = true, default-features = false, features = [ "alloc", ] } @@ -361,6 +362,13 @@ runtime-benchmarks = [ "snowbridge-pallet-system/runtime-benchmarks", "pallet-outbound-commitment-store/runtime-benchmarks", "pallet-datahaven-native-transfer/runtime-benchmarks", + # StorageHub pallets + "pallet-nfts/runtime-benchmarks", + "pallet-file-system/runtime-benchmarks", + "pallet-proofs-dealer/runtime-benchmarks", + "pallet-payment-streams/runtime-benchmarks", + "pallet-storage-providers/runtime-benchmarks", + "dep:k256", ] try-runtime = [ diff --git a/operator/runtime/stagenet/src/benchmarks.rs b/operator/runtime/stagenet/src/benchmarks.rs index 51f38f33..bfbaa347 100644 --- a/operator/runtime/stagenet/src/benchmarks.rs +++ b/operator/runtime/stagenet/src/benchmarks.rs @@ -27,6 +27,7 @@ frame_benchmarking::define_benchmarks!( // Substrate pallets [pallet_balances, Balances] + [pallet_session, pallet_session_benchmarking::Pallet::] // FIXME: benchmarking identity fail // [pallet_identity, Identity] [pallet_im_online, ImOnline] @@ -44,6 +45,13 @@ frame_benchmarking::define_benchmarks!( [pallet_safe_mode, SafeMode] [pallet_tx_pause, TxPause] + // StorageHub pallets + [pallet_nfts, Nfts] + [pallet_file_system, FileSystem] + [pallet_proofs_dealer, ProofsDealer] + [pallet_payment_streams, PaymentStreams] + [pallet_storage_providers, Providers] + // Governance pallets [pallet_collective_technical_committee, TechnicalCommittee] [pallet_collective_treasury_council, TreasuryCouncil] diff --git a/operator/runtime/stagenet/src/configs/mod.rs b/operator/runtime/stagenet/src/configs/mod.rs index 0e2d181f..b07e9a5c 100644 --- a/operator/runtime/stagenet/src/configs/mod.rs +++ b/operator/runtime/stagenet/src/configs/mod.rs @@ -91,7 +91,6 @@ use datahaven_runtime_common::{ }, time::{EpochDurationInBlocks, SessionsPerEra, DAYS, MILLISECS_PER_BLOCK}, }; -use dhp_bridge::{EigenLayerMessageProcessor, NativeTokenTransferMessageProcessor}; use frame_support::{ derive_impl, dispatch::DispatchClass, @@ -126,7 +125,7 @@ use snowbridge_core::{gwei, meth, AgentIdOf, PricingParameters, Rewards, TokenId use snowbridge_inbound_queue_primitives::RewardLedger; use snowbridge_outbound_queue_primitives::{ v1::{Fee, Message, SendMessage}, - v2::{Command, ConstantGasMeter}, + v2::ConstantGasMeter, SendError, SendMessageFeeProvider, }; use snowbridge_pallet_outbound_queue_v2::OnNewCommitment; @@ -387,7 +386,7 @@ impl pallet_session::Config for Runtime { >; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - type WeightInfo = pallet_session::weights::SubstrateWeight; + type WeightInfo = stagenet_weights::pallet_session::WeightInfo; } parameter_types! { @@ -1038,8 +1037,8 @@ impl pallet_evm_chain_id::Config for Runtime {} // --- Snowbridge Config Constants & Parameter Types --- parameter_types! { - // Hoodi testnet genesis hash - pub const StagenetGenesisHash: [u8; 32] = hex_literal::hex!("bbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b"); + // DataHaven stagenet genesis hash + pub const StagenetGenesisHash: [u8; 32] = hex_literal::hex!("72d0856fd339e09cb21df7bac8ac3120bd871e327ec0e1658395df68acef9bee"); pub UniversalLocation: InteriorLocation = [ GlobalConsensus(ByGenesis(StagenetGenesisHash::get())) ].into(); @@ -1105,47 +1104,13 @@ impl snowbridge_pallet_system_v2::Config for Runtime { type Helper = (); } -// Fork versions for runtime benchmarks - must match the fixtures for BLS verification to work -// The fixtures are generated with standard testnet fork versions -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub const ChainForkVersions: ForkVersions = ForkVersions { - genesis: Fork { - version: hex_literal::hex!("00000000"), - epoch: 0, - }, - altair: Fork { - version: hex_literal::hex!("01000000"), - epoch: 0, - }, - bellatrix: Fork { - version: hex_literal::hex!("02000000"), - epoch: 0, - }, - capella: Fork { - version: hex_literal::hex!("03000000"), - epoch: 0, - }, - deneb: Fork { - version: hex_literal::hex!("04000000"), - epoch: 0, - }, - electra: Fork { - version: hex_literal::hex!("05000000"), - epoch: 80000000000, - }, - fulu: Fork { - version: hex_literal::hex!("06000000"), - epoch: 90000000000, - }, - }; -} - // For tests, fast-runtime and std configurations we use the mocked fork versions // These match the fork versions used by the local Ethereum network in E2E tests -#[cfg(all( - any(feature = "std", feature = "fast-runtime", test), - not(feature = "runtime-benchmarks") +#[cfg(any( + feature = "std", + feature = "fast-runtime", + feature = "runtime-benchmarks", + test ))] parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { @@ -1275,8 +1240,8 @@ impl snowbridge_pallet_inbound_queue_v2::Config for Runtime { type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress; #[cfg(not(feature = "runtime-benchmarks"))] type MessageProcessor = ( - EigenLayerMessageProcessor, - NativeTokenTransferMessageProcessor, + dhp_bridge::EigenLayerMessageProcessor, + dhp_bridge::NativeTokenTransferMessageProcessor, ); #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = NoOpMessageProcessor; @@ -1746,6 +1711,7 @@ mod tests { use snowbridge_inbound_queue_primitives::v2::{ EthereumAsset, Message as SnowbridgeMessage, MessageProcessor, Payload as SnowPayload, }; + use snowbridge_outbound_queue_primitives::v2::Command; use sp_core::H160; use sp_io::TestExternalities; use xcm_builder::GlobalConsensusConvertsFor; @@ -1853,7 +1819,7 @@ mod tests { message_id: EL_MESSAGE_ID, message: BridgeMessage::V1(InboundCommand::ReceiveValidators { validators: Vec::new(), - external_index: 0, + external_index: 1, }), }; @@ -1928,4 +1894,95 @@ mod tests { assert!(result.is_ok(), "Message from authorized origin should be accepted"); }); } + + /// Test that the ExternalValidatorRewardsAccount is correctly derived from the pallet ID. + /// + /// This verifies that `PalletId(*b"dh/evrew").into_account_truncating()` produces the + /// expected AccountId20 value, which is used in the Rewards Agent ID computation. + #[test] + fn test_external_validator_rewards_account_derivation() { + // Expected account: "modl" (4 bytes) + "dh/evrew" (8 bytes) + zeros (8 bytes) = 20 bytes + // "modl" = 0x6d6f646c + // "dh/evrew" = 0x64682f6576726577 + // Result = 0x6d6f646c64682f65767265770000000000000000 + let expected_account = AccountId::from(hex_literal::hex!( + "6d6f646c64682f65767265770000000000000000" + )); + + let actual_account = ExternalValidatorRewardsAccount::get(); + + assert_eq!( + actual_account, expected_account, + "ExternalValidatorRewardsAccount must be derived correctly from PalletId 'dh/evrew'" + ); + } + + /// Test that the Rewards Agent ID (used for Snowbridge outbound messages from the rewards pallet) + /// is correctly computed from the chain's genesis hash and the ExternalValidatorRewardsAccount. + /// + /// This test verifies the value that should be set as `RewardsAgentOrigin` in runtime parameters + /// and as `rewardsMessageOrigin` in the AVS contract configuration. + /// + /// The Agent ID is computed following Snowbridge's pattern for GlobalConsensus locations: + /// blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), compact_len, "AccountKey20", account_key)) + /// + /// Note: Standard `AgentIdOf` doesn't support direct AccountKey20 without a Parachain junction, + /// so we compute the hash directly here. + #[test] + fn test_rewards_agent_id_computation() { + use codec::Encode; + use sp_core::H256; + use sp_io::hashing::blake2_256; + use xcm::prelude::NetworkId; + + // Use the StagenetGenesisHash parameter + let genesis_hash: [u8; 32] = StagenetGenesisHash::get(); + + // Get the rewards pallet account (derived from PalletId "dh/evrew") + let rewards_account: [u8; 20] = ExternalValidatorRewardsAccount::get().into(); + + // Build the location description following Snowbridge's encoding pattern: + // ("GlobalConsensus", ByGenesis(genesis_hash), compact_len(interior), "AccountKey20", account_key) + // + // This matches the pattern in snowbridge_core::location::DescribeGlobalPrefix + // combined with DescribeTokenTerminal for AccountKey20. + + // Interior description: "AccountKey20" + account_key (no length prefix for fixed arrays) + let interior: Vec = (b"AccountKey20", rewards_account).encode(); + + // Full encoding: "GlobalConsensus" + NetworkId::ByGenesis(genesis) + interior + let encoded: Vec = ( + b"GlobalConsensus", + NetworkId::ByGenesis(genesis_hash), + interior, + ) + .encode(); + + // Hash with blake2_256 + let computed_agent_id = H256(blake2_256(&encoded)); + + // Expected Agent ID - this value must match RewardsAgentOrigin in runtime_params.rs + // If this test fails, update RewardsAgentOrigin to match the computed value. + let expected_agent_id = H256(hex_literal::hex!( + "56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd" + )); + + assert_eq!( + computed_agent_id, + expected_agent_id, + "Computed Rewards Agent ID must match expected value.\n\ + This value should be set as:\n\ + - RewardsAgentOrigin in runtime_params.rs\n\ + - rewardsMessageOrigin in AVS contract config\n\ + \n\ + Rewards account: 0x{}\n\ + Genesis hash: 0x{}\n\ + Computed: {:?}\n\ + Expected: {:?}", + hex::encode(rewards_account), + hex::encode(genesis_hash), + computed_agent_id, + expected_agent_id + ); + } } diff --git a/operator/runtime/stagenet/src/configs/runtime_params.rs b/operator/runtime/stagenet/src/configs/runtime_params.rs index 26517b51..f05caff5 100644 --- a/operator/runtime/stagenet/src/configs/runtime_params.rs +++ b/operator/runtime/stagenet/src/configs/runtime_params.rs @@ -51,10 +51,14 @@ pub mod dynamic_params { #[codec(index = 3)] #[allow(non_upper_case_globals)] - /// The RewardsAgentOrigin is the origin of the rewards agent, which is its ID. - /// TODO: Decide which agent origin we want to use. Currently for testing it's the zero hash + /// The RewardsAgentOrigin is the Agent ID for the rewards pallet's outbound Snowbridge messages. + /// Computed as: blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), interior)) + /// where interior = SCALE_ENCODE("AccountKey20", ExternalValidatorRewardsAccount) + /// + /// For stagenet with genesis hash 0x72d0856fd339e09cb21df7bac8ac3120bd871e327ec0e1658395df68acef9bee + /// and rewards account 0x6d6f646c64682f65767265770000000000000000 (from PalletId "dh/evrew"): pub static RewardsAgentOrigin: H256 = H256::from_slice(&hex!( - "0000000000000000000000000000000000000000000000000000000000000000" + "56490bd3f367447bfaf57bb18e7a45e1b2db7d538fe42098e87d2aa106c6afdd" )); // Proportion of fees allocated to the Treasury (remainder are burned). @@ -131,9 +135,9 @@ pub mod dynamic_params { /// /// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] ) /// - /// 500 = 50 + u * (e ^ (1 - 0.95) - 1) - /// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777 - pub static UpperExponentFactor: u32 = 8777; + /// 500 GIGAWEI = 50 GIGAWEI + u * (e ^ (1 - 0.95) - 1) + /// u = (500 GIGAWEI - 50 GIGAWEI) / (e ^ (1 - 0.95) - 1) ≈ 8,776,874,921,880 + pub static UpperExponentFactor: Balance = 8_776_874_921_880; #[codec(index = 15)] #[allow(non_upper_case_globals)] @@ -142,9 +146,9 @@ pub mod dynamic_params { /// /// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 ) /// - /// 10 = 50 - l * (e ^ (0.3 - 0) - 1) - /// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114 - pub static LowerExponentFactor: u32 = 114; + /// 10 GIGAWEI = 50 GIGAWEI - l * (e ^ (0.3 - 0) - 1) + /// l = (50 GIGAWEI - 10 GIGAWEI) / (e ^ (0.3 - 0) - 1) ≈ 114,331,836,540 + pub static LowerExponentFactor: Balance = 114_331_836_540; #[codec(index = 16)] #[allow(non_upper_case_globals)] diff --git a/operator/runtime/stagenet/src/configs/storagehub/mod.rs b/operator/runtime/stagenet/src/configs/storagehub/mod.rs index ca2f1d30..79a71b14 100644 --- a/operator/runtime/stagenet/src/configs/storagehub/mod.rs +++ b/operator/runtime/stagenet/src/configs/storagehub/mod.rs @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with DataHaven. If not, see . +#[cfg(not(feature = "runtime-benchmarks"))] +use super::HAVE; +#[cfg(feature = "runtime-benchmarks")] +use super::MICROHAVE; use super::{ AccountId, Balance, Balances, BlockNumber, Hash, RuntimeEvent, RuntimeHoldReason, - TreasuryAccount, HAVE, + TreasuryAccount, }; use crate::configs::runtime_params::dynamic_params::runtime_config; use crate::{ @@ -24,6 +28,8 @@ use crate::{ HOURS, }; use core::marker::PhantomData; +#[cfg(feature = "runtime-benchmarks")] +use datahaven_runtime_common::benchmarking::StorageHubBenchmarking; use datahaven_runtime_common::time::{DAYS, MINUTES}; use frame_support::pallet_prelude::DispatchClass; use frame_support::traits::AsEnsureOriginWithArg; @@ -33,7 +39,7 @@ use frame_support::{ weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use frame_system::{EnsureRoot, EnsureSigned}; +use frame_system::EnsureSigned; use num_bigint::BigUint; use pallet_nfts::PalletFeatures; use polkadot_runtime_common::prod_or_fast; @@ -68,6 +74,7 @@ pub type StorageProofsMerkleTrieLayout = LayoutV1; pub type Hashing = BlakeTwo256; /****** NFTs pallet ******/ +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const CollectionDeposit: Balance = 100 * HAVE; pub const ItemDeposit: Balance = 1 * HAVE; @@ -80,6 +87,19 @@ parameter_types! { pub const MaxAttributesPerCall: u32 = 10; pub Features: PalletFeatures = PalletFeatures::all_enabled(); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const CollectionDeposit: Balance = 100 * MICROHAVE; + pub const ItemDeposit: Balance = 1 * MICROHAVE; + pub const MetadataDepositBase: Balance = 10 * MICROHAVE; + pub const MetadataDepositPerByte: Balance = 1 * MICROHAVE; + pub const ApprovalsLimit: u32 = 20; + pub const ItemAttributesApprovalsLimit: u32 = 20; + pub const MaxTips: u32 = 10; + pub const MaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; + pub const MaxAttributesPerCall: u32 = 10; + pub Features: PalletFeatures = PalletFeatures::all_enabled(); +} impl pallet_nfts::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -104,11 +124,66 @@ impl pallet_nfts::Config for Runtime { type Features = Features; type OffchainSignature = Signature; type OffchainPublic = ::Signer; - type WeightInfo = pallet_nfts::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_nfts::WeightInfo; type Locker = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = benchmark_helpers::NftHelper; } /****** ****** ****** ******/ +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmark_helpers { + use crate::{AccountId, Signature}; + use k256::ecdsa::SigningKey; + use sp_runtime::traits::{IdentifyAccount, Verify}; + use sp_runtime::MultiSignature; + + const BENCH_SIGNING_KEY: [u8; 32] = [1u8; 32]; + + fn bench_signing_key() -> SigningKey { + SigningKey::from_bytes(&BENCH_SIGNING_KEY.into()) + .expect("benchmark signing key is valid; qed") + } + + /// Benchmark helper for NFTs pallet + pub struct NftHelper; + + impl pallet_nfts::BenchmarkHelper::Signer, AccountId, Signature> + for NftHelper + { + fn collection(i: u16) -> u32 { + i.into() + } + + fn item(i: u16) -> u32 { + i.into() + } + + fn signer() -> (::Signer, AccountId) { + let signing_key = bench_signing_key(); + let verifying_key = signing_key.verifying_key(); + let encoded = verifying_key.to_encoded_point(true); + let public = + sp_core::ecdsa::Public::from_full(encoded.as_bytes()).expect("valid key; qed"); + let public_key: ::Signer = public.into(); + let account: AccountId = public_key.clone().into_account(); + (public_key, account) + } + + fn sign(_public: &::Signer, message: &[u8]) -> Signature { + let digest = sp_io::hashing::keccak_256(message); + let (sig, recovery_id) = bench_signing_key() + .sign_prehash_recoverable(&digest) + .expect("signing with fixed key never fails; qed"); + let mut sig_bytes = [0u8; 65]; + sig_bytes[..64].copy_from_slice(&sig.to_bytes()); + sig_bytes[64] = recovery_id.to_byte(); + let sig = sp_core::ecdsa::Signature::from_raw(sig_bytes); + Signature::from(MultiSignature::Ecdsa(sig)) + } + } +} + /****** Relay Randomness pallet ******/ impl pallet_randomness::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -151,6 +226,7 @@ impl sp_runtime::traits::BlockNumberProvider for BlockNumberGetter { /****** ****** ****** ******/ /****** Storage Providers pallet ******/ +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const SpMinDeposit: Balance = 100 * HAVE; pub const BucketDeposit: Balance = 100 * HAVE; @@ -159,10 +235,47 @@ parameter_types! { // TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues) // pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const SpMinDeposit: Balance = StorageHubBenchmarking::SP_MIN_DEPOSIT; + pub const BucketDeposit: Balance = StorageHubBenchmarking::BUCKET_DEPOSIT; + pub const BspSignUpLockPeriod: BlockNumber = 90 * DAYS; // ~3 months + pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * HOURS, 2 * MINUTES); + // TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues) + // pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES); +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct StorageHubTreasuryAccount; +#[cfg(feature = "runtime-benchmarks")] +impl Get for StorageHubTreasuryAccount { + fn get() -> AccountId { + let account = TreasuryAccount::get(); + StorageHubBenchmarking::ensure_treasury_account::(account) + } +} + +// Benchmark helpers for Storage Providers pallet. +#[cfg(feature = "runtime-benchmarks")] +pub struct ProvidersBenchmarkHelpers; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_storage_providers::benchmarking::BenchmarkHelpers + for ProvidersBenchmarkHelpers +{ + type ProviderId = ::ProviderId; + + fn set_accrued_failed_proofs(provider_id: Self::ProviderId, value: u32) { + pallet_proofs_dealer::SlashableProviders::::insert(provider_id, value); + } + + fn get_accrued_failed_proofs(provider_id: Self::ProviderId) -> u32 { + pallet_proofs_dealer::SlashableProviders::::get(provider_id).unwrap_or(0) + } +} impl pallet_storage_providers::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_storage_providers::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_storage_providers::WeightInfo; type ProvidersRandomness = pallet_randomness::RandomnessFromOneEpochAgo; type PaymentStreams = PaymentStreams; type ProofDealer = ProofsDealer; @@ -188,7 +301,10 @@ impl pallet_storage_providers::Config for Runtime { type ProvidersProofSubmitters = ProofsDealer; type ReputationWeightType = u32; type StorageHubTickGetter = ProofsDealer; + #[cfg(not(feature = "runtime-benchmarks"))] type Treasury = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type Treasury = StorageHubTreasuryAccount; type SpMinDeposit = SpMinDeposit; type SpMinCapacity = ConstU64<2>; type DepositPerData = ConstU128<2>; @@ -208,6 +324,8 @@ impl pallet_storage_providers::Config for Runtime { type ZeroSizeBucketFixedRate = runtime_config::ZeroSizeBucketFixedRate; type ProviderTopUpTtl = runtime_config::ProviderTopUpTtl; type MaxExpiredItemsInBlock = ConstU32<100>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelpers = ProvidersBenchmarkHelpers; } pub struct StorageDataUnitAndBalanceConverter; @@ -240,7 +358,7 @@ parameter_types! { impl pallet_payment_streams::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_payment_streams::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_payment_streams::WeightInfo; type NativeBalance = Balances; type ProvidersPallet = Providers; type RuntimeHoldReason = RuntimeHoldReason; @@ -250,7 +368,10 @@ impl pallet_payment_streams::Config for Runtime { type BlockNumberToBalance = BlockNumberToBalance; type ProvidersProofSubmitters = ProofsDealer; type TreasuryCutCalculator = LinearThenPowerOfTwoTreasuryCutCalculator; + #[cfg(not(feature = "runtime-benchmarks"))] type TreasuryAccount = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type TreasuryAccount = StorageHubTreasuryAccount; type MaxUsersToCharge = ConstU32<10>; type BaseDeposit = ConstU128<10>; } @@ -279,6 +400,14 @@ const MAX_CUSTOM_CHALLENGES_PER_BLOCK: u32 = 10; const TOTAL_MAX_CHALLENGES_PER_BLOCK: u32 = RANDOM_CHALLENGES_PER_BLOCK + MAX_CUSTOM_CHALLENGES_PER_BLOCK; +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BenchmarkStakeToChallengePeriod: Balance = + StorageHubBenchmarking::STAKE_TO_CHALLENGE_PERIOD; + pub const BenchmarkCheckpointChallengePeriod: BlockNumber = + StorageHubBenchmarking::CHECKPOINT_CHALLENGE_PERIOD; +} + parameter_types! { pub const RandomChallengesPerBlock: u32 = RANDOM_CHALLENGES_PER_BLOCK; pub const MaxCustomChallengesPerBlock: u32 = MAX_CUSTOM_CHALLENGES_PER_BLOCK; @@ -293,7 +422,7 @@ parameter_types! { impl pallet_proofs_dealer::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_proofs_dealer::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_proofs_dealer::WeightInfo; type ProvidersPallet = Providers; type NativeBalance = Balances; type MerkleTrieHash = Hash; @@ -306,29 +435,50 @@ impl pallet_proofs_dealer::Config for Runtime { { shp_constants::FILE_SIZE_TO_CHALLENGES }, >; type StakeToBlockNumber = SaturatingBalanceToBlockNumber; + #[cfg(feature = "runtime-benchmarks")] + type RandomChallengesPerBlock = ConstU32<0>; + #[cfg(not(feature = "runtime-benchmarks"))] type RandomChallengesPerBlock = RandomChallengesPerBlock; + #[cfg(feature = "runtime-benchmarks")] + type MaxCustomChallengesPerBlock = TotalMaxChallengesPerBlock; + #[cfg(not(feature = "runtime-benchmarks"))] type MaxCustomChallengesPerBlock = MaxCustomChallengesPerBlock; type MaxSubmittersPerTick = MaxSubmittersPerTick; type TargetTicksStorageOfSubmitters = TargetTicksStorageOfSubmitters; type ChallengeHistoryLength = ChallengeHistoryLength; type ChallengesQueueLength = ChallengesQueueLength; + #[cfg(not(feature = "runtime-benchmarks"))] type CheckpointChallengePeriod = runtime_config::CheckpointChallengePeriod; + #[cfg(feature = "runtime-benchmarks")] + type CheckpointChallengePeriod = BenchmarkCheckpointChallengePeriod; type ChallengesFee = ChallengesFee; type PriorityChallengesFee = PriorityChallengesFee; + #[cfg(not(feature = "runtime-benchmarks"))] type Treasury = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type Treasury = StorageHubTreasuryAccount; // TODO: Once the client logic to keep track of CR randomness deadlines and execute their submissions is implemented // AND after the chain has been live for enough time to have enough providers to avoid the commit-reveal randomness being // gameable, the randomness provider should be CrRandomness type RandomnessProvider = pallet_randomness::ParentBlockRandomness; + #[cfg(not(feature = "runtime-benchmarks"))] type StakeToChallengePeriod = runtime_config::StakeToChallengePeriod; + #[cfg(feature = "runtime-benchmarks")] + type StakeToChallengePeriod = BenchmarkStakeToChallengePeriod; type MinChallengePeriod = runtime_config::MinChallengePeriod; type ChallengeTicksTolerance = ChallengeTicksTolerance; type BlockFullnessPeriod = ChallengeTicksTolerance; // We purposely set this to `ChallengeTicksTolerance` so that spamming of the chain is evaluated for the same blocks as the tolerance BSPs are given. type BlockFullnessHeadroom = BlockFullnessHeadroom; type MinNotFullBlocksRatio = MinNotFullBlocksRatio; type MaxSlashableProvidersPerTick = MaxSlashableProvidersPerTick; - type ChallengeOrigin = EnsureRoot; - type PriorityChallengeOrigin = EnsureRoot; + #[cfg(not(feature = "runtime-benchmarks"))] + type ChallengeOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ChallengeOrigin = EnsureSigned; + #[cfg(not(feature = "runtime-benchmarks"))] + type PriorityChallengeOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type PriorityChallengeOrigin = EnsureSigned; } // Converter from the Balance type to the BlockNumber type for math. @@ -452,12 +602,24 @@ impl Get for MaxSlashableProvidersPerTick { type ThresholdType = u32; pub type ReplicationTargetType = u32; +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const BaseStorageRequestCreationDeposit: Balance = 1 * HAVE; pub const FileDeletionRequestCreationDeposit: Balance = 1 * HAVE; pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold); pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BaseStorageRequestCreationDeposit: Balance = 1 * MICROHAVE; + pub const FileDeletionRequestCreationDeposit: Balance = 1 * MICROHAVE; + pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold); + pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold); +} +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BenchmarkBspStopStoringFilePenalty: Balance = 1 * MICROHAVE; +} // Converts a given signed message in a EIP-191 compliant message bytes to verify. /// EIP-191: https://eips.ethereum.org/EIPS/eip-191 @@ -480,7 +642,7 @@ impl shp_traits::MessageAdapter for Eip191Adapter { impl pallet_file_system::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_file_system::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_file_system::WeightInfo; type Providers = Providers; type ProofDealer = ProofsDealer; type PaymentStreams = PaymentStreams; @@ -500,8 +662,14 @@ impl pallet_file_system::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type Nfts = Nfts; type CollectionInspector = BucketNfts; + #[cfg(not(feature = "runtime-benchmarks"))] type BspStopStoringFilePenalty = runtime_config::BspStopStoringFilePenalty; + #[cfg(feature = "runtime-benchmarks")] + type BspStopStoringFilePenalty = BenchmarkBspStopStoringFilePenalty; + #[cfg(not(feature = "runtime-benchmarks"))] type TreasuryAccount = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type TreasuryAccount = StorageHubTreasuryAccount; type MaxBatchConfirmStorageRequests = ConstU32<100>; type MaxFilePathSize = ConstU32<512u32>; type MaxPeerIdSize = ConstU32<100>; diff --git a/operator/runtime/stagenet/src/genesis_config_presets.rs b/operator/runtime/stagenet/src/genesis_config_presets.rs index 2fcbd983..0265f5a3 100644 --- a/operator/runtime/stagenet/src/genesis_config_presets.rs +++ b/operator/runtime/stagenet/src/genesis_config_presets.rs @@ -267,7 +267,7 @@ pub fn dorothy() -> AccountId { } pub fn ethan() -> AccountId { - AccountId::from(hex!("Ff64d3F6efE2317EE2807d2235B1ac2AA69d9E87")) + AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")) } pub fn frank() -> AccountId { diff --git a/operator/runtime/stagenet/src/lib.rs b/operator/runtime/stagenet/src/lib.rs index 36f69c61..b78a265e 100644 --- a/operator/runtime/stagenet/src/lib.rs +++ b/operator/runtime/stagenet/src/lib.rs @@ -145,7 +145,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 1000, + spec_version: 1300, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -203,7 +203,7 @@ parameter_types! { parameter_types! { // TODO: Change ED to 1 after upgrade to Polkadot SDK stable2503 // cfr. https://github.com/paritytech/polkadot-sdk/pull/7379 - pub const ExistentialDeposit: Balance = 100; + pub const ExistentialDeposit: Balance = 1; } /// The version information used to identify this runtime when compiled natively. @@ -974,6 +974,7 @@ impl_runtime_apis! { use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} + impl pallet_session_benchmarking::Config for Runtime {} impl baseline::Config for Runtime {} use frame_support::traits::WhitelistedStorageKeys; @@ -1266,6 +1267,9 @@ impl_runtime_apis! { ) -> Vec { FileSystem::query_pending_bsp_confirm_storage_requests(bsp_id, file_keys) } + fn get_max_batch_confirm_storage_requests() -> BlockNumber { + FileSystem::get_max_batch_confirm_storage_requests() + } } impl pallet_payment_streams_runtime_api::PaymentStreamsApi, Balance, AccountId> for Runtime { diff --git a/operator/runtime/stagenet/src/weights/mod.rs b/operator/runtime/stagenet/src/weights/mod.rs index 25a54307..354a9cbd 100644 --- a/operator/runtime/stagenet/src/weights/mod.rs +++ b/operator/runtime/stagenet/src/weights/mod.rs @@ -35,8 +35,13 @@ pub mod pallet_babe; pub mod pallet_balances; pub mod pallet_beefy_mmr; pub mod pallet_evm; +pub mod pallet_file_system; pub mod pallet_grandpa; +pub mod pallet_nfts; +pub mod pallet_payment_streams; +pub mod pallet_proofs_dealer; pub mod pallet_randomness; +pub mod pallet_storage_providers; // pub mod pallet_identity; pub mod pallet_im_online; pub mod pallet_message_queue; @@ -48,6 +53,7 @@ pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_safe_mode; pub mod pallet_scheduler; +pub mod pallet_session; pub mod pallet_sudo; pub mod pallet_timestamp; pub mod pallet_transaction_payment; diff --git a/operator/runtime/stagenet/src/weights/pallet_file_system.rs b/operator/runtime/stagenet/src/weights/pallet_file_system.rs new file mode 100644 index 00000000..4a2a2050 --- /dev/null +++ b/operator/runtime/stagenet/src/weights/pallet_file_system.rs @@ -0,0 +1,5 @@ +//! Weights for `pallet_file_system`. +//! +//! Generated weights should overwrite this file. + +pub use pallet_file_system::weights::SubstrateWeight as WeightInfo; diff --git a/operator/runtime/stagenet/src/weights/pallet_nfts.rs b/operator/runtime/stagenet/src/weights/pallet_nfts.rs new file mode 100644 index 00000000..852419ff --- /dev/null +++ b/operator/runtime/stagenet/src/weights/pallet_nfts.rs @@ -0,0 +1,728 @@ + + +//! Autogenerated weights for `pallet_nfts` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2025-11-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.compact.compressed.wasm +// --pallet +// pallet_nfts +// --extrinsic +// +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/stagenet/src/weights/pallet_nfts.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_nfts`. +pub struct WeightInfo(PhantomData); +impl pallet_nfts::WeightInfo for WeightInfo { + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `271` + // Estimated: `3537` + // Minimum execution time: 47_279_000 picoseconds. + Weight::from_parts(48_666_000, 3537) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn force_create() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3537` + // Minimum execution time: 25_473_000 picoseconds. + Weight::from_parts(26_241_000, 3537) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// The range of component `m` is `[0, 1000]`. + /// The range of component `c` is `[0, 1000]`. + /// The range of component `a` is `[0, 1000]`. + fn destroy(m: u32, c: u32, a: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `32179 + a * (366 ±0)` + // Estimated: `2523990 + a * (2930 ±0)` + // Minimum execution time: 1_381_577_000 picoseconds. + Weight::from_parts(756_122_428, 2523990) + // Standard Error: 12_048 + .saturating_add(Weight::from_parts(476_790, 0).saturating_mul(m.into())) + // Standard Error: 12_048 + .saturating_add(Weight::from_parts(51_253, 0).saturating_mul(c.into())) + // Standard Error: 12_048 + .saturating_add(Weight::from_parts(8_131_406, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1004_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) + .saturating_add(T::DbWeight::get().writes(1005_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(a.into())) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + fn mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `418` + // Estimated: `4062` + // Minimum execution time: 67_882_000 picoseconds. + Weight::from_parts(69_718_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + fn force_mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `418` + // Estimated: `4062` + // Minimum execution time: 65_679_000 picoseconds. + Weight::from_parts(66_549_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn burn() -> Weight { + // Proof Size summary in bytes: + // Measured: `526` + // Estimated: `4062` + // Minimum execution time: 73_580_000 picoseconds. + Weight::from_parts(75_125_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `555` + // Estimated: `4062` + // Minimum execution time: 56_312_000 picoseconds. + Weight::from_parts(58_020_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:5000 w:5000) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 5000]`. + fn redeposit(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `750 + i * (83 ±0)` + // Estimated: `3538 + i * (3072 ±0)` + // Minimum execution time: 19_062_000 picoseconds. + Weight::from_parts(19_305_000, 3538) + // Standard Error: 24_093 + .saturating_add(Weight::from_parts(25_028_153, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) + .saturating_add(Weight::from_parts(0, 3072).saturating_mul(i.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn lock_item_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 24_311_000 picoseconds. + Weight::from_parts(24_973_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn unlock_item_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 24_194_000 picoseconds. + Weight::from_parts(24_755_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn lock_collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `327` + // Estimated: `3538` + // Minimum execution time: 19_916_000 picoseconds. + Weight::from_parts(20_550_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn transfer_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `524` + // Estimated: `3581` + // Minimum execution time: 35_006_000 picoseconds. + Weight::from_parts(35_968_000, 3581) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + fn set_team() -> Weight { + // Proof Size summary in bytes: + // Measured: `344` + // Estimated: `6054` + // Minimum execution time: 49_456_000 picoseconds. + Weight::from_parts(50_590_000, 6054) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn force_collection_owner() -> Weight { + // Proof Size summary in bytes: + // Measured: `298` + // Estimated: `3537` + // Minimum execution time: 20_463_000 picoseconds. + Weight::from_parts(20_872_000, 3537) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn force_collection_config() -> Weight { + // Proof Size summary in bytes: + // Measured: `276` + // Estimated: `3537` + // Minimum execution time: 16_403_000 picoseconds. + Weight::from_parts(17_022_000, 3537) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn lock_item_properties() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 22_791_000 picoseconds. + Weight::from_parts(23_182_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + fn set_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `514` + // Estimated: `3920` + // Minimum execution time: 68_893_000 picoseconds. + Weight::from_parts(70_418_000, 3920) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + fn force_set_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `331` + // Estimated: `3920` + // Minimum execution time: 33_040_000 picoseconds. + Weight::from_parts(33_469_000, 3920) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + fn clear_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `958` + // Estimated: `3920` + // Minimum execution time: 62_760_000 picoseconds. + Weight::from_parts(64_137_000, 3920) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + fn approve_item_attributes() -> Weight { + // Proof Size summary in bytes: + // Measured: `356` + // Estimated: `4062` + // Minimum execution time: 20_851_000 picoseconds. + Weight::from_parts(21_234_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn cancel_item_attributes_approval(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `769 + n * (386 ±0)` + // Estimated: `4062 + n * (2930 ±0)` + // Minimum execution time: 32_914_000 picoseconds. + Weight::from_parts(33_415_000, 4062) + // Standard Error: 7_498 + .saturating_add(Weight::from_parts(7_720_860, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + fn set_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `514` + // Estimated: `3800` + // Minimum execution time: 56_827_000 picoseconds. + Weight::from_parts(57_851_000, 3800) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn clear_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `824` + // Estimated: `3800` + // Minimum execution time: 53_669_000 picoseconds. + Weight::from_parts(54_640_000, 3800) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + fn set_collection_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `373` + // Estimated: `3759` + // Minimum execution time: 51_403_000 picoseconds. + Weight::from_parts(52_206_000, 3759) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + fn clear_collection_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `691` + // Estimated: `3759` + // Minimum execution time: 50_720_000 picoseconds. + Weight::from_parts(51_692_000, 3759) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn approve_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `385` + // Estimated: `4062` + // Minimum execution time: 24_116_000 picoseconds. + Weight::from_parts(25_104_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn cancel_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `4062` + // Minimum execution time: 20_907_000 picoseconds. + Weight::from_parts(21_484_000, 4062) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn clear_all_transfer_approvals() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `4062` + // Minimum execution time: 19_916_000 picoseconds. + Weight::from_parts(20_689_000, 4062) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn set_accept_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3505` + // Minimum execution time: 17_199_000 picoseconds. + Weight::from_parts(17_750_000, 3505) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + fn set_collection_max_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `327` + // Estimated: `3538` + // Minimum execution time: 22_256_000 picoseconds. + Weight::from_parts(22_786_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn update_mint_settings() -> Weight { + // Proof Size summary in bytes: + // Measured: `311` + // Estimated: `3538` + // Minimum execution time: 21_133_000 picoseconds. + Weight::from_parts(21_821_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + fn set_price() -> Weight { + // Proof Size summary in bytes: + // Measured: `493` + // Estimated: `4062` + // Minimum execution time: 30_502_000 picoseconds. + Weight::from_parts(31_519_000, 4062) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn buy_item() -> Weight { + // Proof Size summary in bytes: + // Measured: `655` + // Estimated: `4062` + // Minimum execution time: 66_549_000 picoseconds. + Weight::from_parts(67_947_000, 4062) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// The range of component `n` is `[0, 10]`. + fn pay_tips(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_265_000 picoseconds. + Weight::from_parts(4_739_944, 0) + // Standard Error: 7_976 + .saturating_add(Weight::from_parts(2_546_489, 0).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:2 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn create_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `444` + // Estimated: `7134` + // Minimum execution time: 26_741_000 picoseconds. + Weight::from_parts(27_648_000, 7134) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn cancel_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `488` + // Estimated: `4062` + // Minimum execution time: 27_430_000 picoseconds. + Weight::from_parts(28_020_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:2 w:2) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:2 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:4) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + fn claim_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `771` + // Estimated: `7134` + // Minimum execution time: 109_567_000 picoseconds. + Weight::from_parts(111_480_000, 7134) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(10_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn mint_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `580` + // Estimated: `6054 + n * (2930 ±0)` + // Minimum execution time: 159_539_000 picoseconds. + Weight::from_parts(165_962_526, 6054) + // Standard Error: 69_524 + .saturating_add(Weight::from_parts(43_681_845, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn set_attributes_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `575` + // Estimated: `4062 + n * (2930 ±0)` + // Minimum execution time: 75_482_000 picoseconds. + Weight::from_parts(89_133_467, 4062) + // Standard Error: 95_313 + .saturating_add(Weight::from_parts(42_327_087, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } +} diff --git a/operator/runtime/stagenet/src/weights/pallet_payment_streams.rs b/operator/runtime/stagenet/src/weights/pallet_payment_streams.rs new file mode 100644 index 00000000..3ac0c1d5 --- /dev/null +++ b/operator/runtime/stagenet/src/weights/pallet_payment_streams.rs @@ -0,0 +1,449 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_payment_streams` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.compact.compressed.wasm +// --pallet +// pallet_payment_streams +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/stagenet/src/weights/pallet_payment_streams.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_payment_streams`. +pub struct WeightInfo(PhantomData); +impl pallet_payment_streams::weights::WeightInfo for WeightInfo { + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn create_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `523` + // Estimated: `6054` + // Minimum execution time: 109_755_000 picoseconds. + Weight::from_parts(111_256_000, 6054) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn update_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1427` + // Estimated: `12414` + // Minimum execution time: 410_091_000 picoseconds. + Weight::from_parts(423_942_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn delete_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1304` + // Estimated: `12414` + // Minimum execution time: 299_884_000 picoseconds. + Weight::from_parts(304_140_000, 12414) + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:0) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn create_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `525` + // Estimated: `6054` + // Minimum execution time: 111_177_000 picoseconds. + Weight::from_parts(113_406_000, 6054) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn update_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1387` + // Estimated: `12414` + // Minimum execution time: 367_704_000 picoseconds. + Weight::from_parts(372_410_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn delete_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1455` + // Estimated: `12414` + // Minimum execution time: 408_008_000 picoseconds. + Weight::from_parts(420_144_000, 12414) + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn charge_payment_streams() -> Weight { + // Proof Size summary in bytes: + // Measured: `1441` + // Estimated: `12414` + // Minimum execution time: 341_010_000 picoseconds. + Weight::from_parts(353_585_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:10 w:10) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:10 w:10) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:10 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:12 w:12) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn charge_multiple_users_payment_streams(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1122 + n * (331 ±0)` + // Estimated: `12414 + n * (2604 ±0)` + // Minimum execution time: 20_290_000 picoseconds. + Weight::from_parts(44_658_677, 12414) + // Standard Error: 159_356 + .saturating_add(Weight::from_parts(299_090_828, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2604).saturating_mul(n.into())) + } + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1001 w:1001) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:999 w:999) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:999 w:999) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:999 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:999 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:999 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn pay_outstanding_debt(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1422 + n * (644 ±0)` + // Estimated: `12414 + n * (3634 ±0)` + // Minimum execution time: 382_387_000 picoseconds. + Weight::from_parts(386_938_000, 12414) + // Standard Error: 160_843 + .saturating_add(Weight::from_parts(288_094_697, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3634).saturating_mul(n.into())) + } + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:1) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:0) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn clear_insolvent_flag() -> Weight { + // Proof Size summary in bytes: + // Measured: `231` + // Estimated: `3505` + // Minimum execution time: 22_156_000 picoseconds. + Weight::from_parts(23_278_000, 3505) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:1) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn price_index_update() -> Weight { + // Proof Size summary in bytes: + // Measured: `116` + // Estimated: `1501` + // Minimum execution time: 5_701_000 picoseconds. + Weight::from_parts(6_021_000, 1501) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:1) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn tick_update() -> Weight { + // Proof Size summary in bytes: + // Measured: `114` + // Estimated: `1489` + // Minimum execution time: 3_827_000 picoseconds. + Weight::from_parts(4_161_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastSubmittersTickRegistered` (r:1 w:1) + /// Proof: `PaymentStreams::LastSubmittersTickRegistered` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:0) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:0) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:244 w:244) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 244]`. + fn update_providers_last_chargeable_info(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `270 + n * (32 ±0)` + // Estimated: `11295 + n * (2543 ±0)` + // Minimum execution time: 12_555_000 picoseconds. + Weight::from_parts(10_548_186, 11295) + // Standard Error: 4_805 + .saturating_add(Weight::from_parts(7_024_412, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2543).saturating_mul(n.into())) + } +} diff --git a/operator/runtime/stagenet/src/weights/pallet_proofs_dealer.rs b/operator/runtime/stagenet/src/weights/pallet_proofs_dealer.rs new file mode 100644 index 00000000..8fb40c96 --- /dev/null +++ b/operator/runtime/stagenet/src/weights/pallet_proofs_dealer.rs @@ -0,0 +1,326 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_proofs_dealer` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.compact.compressed.wasm +// --pallet +// pallet_proofs_dealer +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/stagenet/src/weights/pallet_proofs_dealer.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_proofs_dealer`. +pub struct WeightInfo(PhantomData); +impl pallet_proofs_dealer::weights::WeightInfo for WeightInfo { + /// Storage: `ProofsDealer::ChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + fn challenge() -> Weight { + // Proof Size summary in bytes: + // Measured: `41` + // Estimated: `4687` + // Minimum execution time: 11_702_000 picoseconds. + Weight::from_parts(12_152_000, 4687) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:2 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:1 w:0) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:5 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:2) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 20]`. + fn submit_proof_no_checkpoint_challenges_key_proofs(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2070` + // Estimated: `15270` + // Minimum execution time: 2_158_744_000 picoseconds. + Weight::from_parts(2_068_488_029, 15270) + // Standard Error: 330_919 + .saturating_add(Weight::from_parts(133_424_014, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(30_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:1 w:0) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:2) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// The range of component `n` is `[21, 40]`. + fn submit_proof_with_checkpoint_challenges_key_proofs(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2070` + // Estimated: `20676` + // Minimum execution time: 4_534_427_000 picoseconds. + Weight::from_parts(3_936_459_939, 20676) + // Standard Error: 918_274 + .saturating_add(Weight::from_parts(38_816_629, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(39_u64)) + .saturating_add(T::DbWeight::get().writes(11_u64)) + } + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestParentBlockRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestParentBlockRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckForSlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::TickToCheckForSlashableProviders` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:1001 w:2000) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1000 w:1000) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1000 w:1000) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1000 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1000 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:0 w:1) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn new_challenges_round(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1155 + n * (271 ±0)` + // Estimated: `6172 + n * (3634 ±0)` + // Minimum execution time: 29_919_000 picoseconds. + Weight::from_parts(30_247_000, 6172) + // Standard Error: 50_330 + .saturating_add(Weight::from_parts(40_561_686, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3634).saturating_mul(n.into())) + } + /// Storage: `ProofsDealer::PriorityChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::PriorityChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:1) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:0 w:2) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 20]`. + fn new_checkpoint_challenge_round(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `65 + n * (32 ±0)` + // Estimated: `4787` + // Minimum execution time: 14_102_000 picoseconds. + Weight::from_parts(16_065_088, 4787) + // Standard Error: 3_474 + .saturating_add(Weight::from_parts(431_594, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `ProofsDealer::PastBlocksStatus` (r:1 w:1) + /// Proof: `ProofsDealer::PastBlocksStatus` (`max_values`: Some(1), `max_size`: Some(51), added: 546, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::PastBlocksWeight` (r:1 w:0) + /// Proof: `ProofsDealer::PastBlocksWeight` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTickerPaused` (r:0 w:1) + /// Proof: `ProofsDealer::ChallengesTickerPaused` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `MaxEncodedLen`) + fn check_spamming_condition() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `3501` + // Minimum execution time: 14_156_000 picoseconds. + Weight::from_parts(14_699_000, 3501) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::LastDeletedTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastDeletedTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn trim_valid_proof_submitters_last_ticks_constant_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `41` + // Estimated: `1489` + // Minimum execution time: 4_462_000 picoseconds. + Weight::from_parts(4_676_000, 1489) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `ProofsDealer::LastDeletedTick` (r:0 w:1) + /// Proof: `ProofsDealer::LastDeletedTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:0 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + fn trim_valid_proof_submitters_last_ticks_loop() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_654_000 picoseconds. + Weight::from_parts(2_799_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::PastBlocksWeight` (r:0 w:2) + /// Proof: `ProofsDealer::PastBlocksWeight` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + fn on_finalize() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_988_000 picoseconds. + Weight::from_parts(5_139_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn force_initialise_challenge_cycle() -> Weight { + // Proof Size summary in bytes: + // Measured: `552` + // Estimated: `4624` + // Minimum execution time: 45_404_000 picoseconds. + Weight::from_parts(46_675_000, 4624) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::ChallengesTickerPaused` (r:0 w:1) + /// Proof: `ProofsDealer::ChallengesTickerPaused` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `MaxEncodedLen`) + fn set_paused() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_538_000 picoseconds. + Weight::from_parts(7_804_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} diff --git a/operator/runtime/stagenet/src/weights/pallet_session.rs b/operator/runtime/stagenet/src/weights/pallet_session.rs new file mode 100644 index 00000000..9c65f513 --- /dev/null +++ b/operator/runtime/stagenet/src/weights/pallet_session.rs @@ -0,0 +1,84 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_session` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.compact.compressed.wasm +// --pallet +// pallet_session +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/stagenet/src/weights/pallet_session.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_session`. +pub struct WeightInfo(PhantomData); +impl pallet_session::WeightInfo for WeightInfo { + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:4 w:4) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `350` + // Estimated: `11240` + // Minimum execution time: 37_322_000 picoseconds. + Weight::from_parts(38_272_000, 11240) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:0 w:4) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn purge_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 21_685_000 picoseconds. + Weight::from_parts(22_489_000, 3793) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } +} diff --git a/operator/runtime/stagenet/src/weights/pallet_storage_providers.rs b/operator/runtime/stagenet/src/weights/pallet_storage_providers.rs new file mode 100644 index 00000000..005a1700 --- /dev/null +++ b/operator/runtime/stagenet/src/weights/pallet_storage_providers.rs @@ -0,0 +1,630 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_storage_providers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-stagenet-runtime/datahaven_stagenet_runtime.compact.compressed.wasm +// --pallet +// pallet_storage_providers +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/stagenet/src/weights/pallet_storage_providers.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_storage_providers`. +pub struct WeightInfo(PhantomData); +impl pallet_storage_providers::weights::WeightInfo for WeightInfo { + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn request_msp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 90_021_000 picoseconds. + Weight::from_parts(92_670_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn request_bsp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 91_611_000 picoseconds. + Weight::from_parts(93_053_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestOneEpochAgoRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestOneEpochAgoRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:0 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn confirm_sign_up_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `474` + // Estimated: `5628` + // Minimum execution time: 38_428_000 picoseconds. + Weight::from_parts(39_861_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestOneEpochAgoRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestOneEpochAgoRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:0 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn confirm_sign_up_msp() -> Weight { + // Proof Size summary in bytes: + // Measured: `487` + // Estimated: `5628` + // Minimum execution time: 54_665_000 picoseconds. + Weight::from_parts(56_343_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn cancel_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `507` + // Estimated: `5628` + // Minimum execution time: 65_055_000 picoseconds. + Weight::from_parts(67_002_000, 5628) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:102 w:101) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 100]`. + fn msp_sign_off(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `775 + n * (83 ±0)` + // Estimated: `8186 + n * (3598 ±0)` + // Minimum execution time: 92_437_000 picoseconds. + Weight::from_parts(92_181_442, 8186) + // Standard Error: 9_739 + .saturating_add(Weight::from_parts(6_392_076, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3598).saturating_mul(n.into())) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:0) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn bsp_sign_off() -> Weight { + // Proof Size summary in bytes: + // Measured: `720` + // Estimated: `4624` + // Minimum execution time: 93_925_000 picoseconds. + Weight::from_parts(95_582_000, 4624) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn change_capacity_bsp_less_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `679` + // Estimated: `4624` + // Minimum execution time: 84_814_000 picoseconds. + Weight::from_parts(86_666_000, 4624) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn change_capacity_bsp_more_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `679` + // Estimated: `4624` + // Minimum execution time: 105_285_000 picoseconds. + Weight::from_parts(106_175_000, 4624) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn change_capacity_msp_less_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `649` + // Estimated: `4608` + // Minimum execution time: 79_570_000 picoseconds. + Weight::from_parts(80_600_000, 4608) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn change_capacity_msp_more_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `649` + // Estimated: `4608` + // Minimum execution time: 99_554_000 picoseconds. + Weight::from_parts(100_542_000, 4608) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + fn add_value_prop() -> Weight { + // Proof Size summary in bytes: + // Measured: `591` + // Estimated: `4608` + // Minimum execution time: 45_279_000 picoseconds. + Weight::from_parts(45_906_000, 4608) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + fn make_value_prop_unavailable() -> Weight { + // Proof Size summary in bytes: + // Measured: `631` + // Estimated: `4608` + // Minimum execution time: 33_017_000 picoseconds. + Weight::from_parts(33_762_000, 4608) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn add_multiaddress() -> Weight { + // Proof Size summary in bytes: + // Measured: `508` + // Estimated: `4624` + // Minimum execution time: 34_075_000 picoseconds. + Weight::from_parts(35_656_000, 4624) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn remove_multiaddress() -> Weight { + // Proof Size summary in bytes: + // Measured: `1316` + // Estimated: `4624` + // Minimum execution time: 32_962_000 picoseconds. + Weight::from_parts(33_729_000, 4624) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:0 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn force_msp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 126_394_000 picoseconds. + Weight::from_parts(129_027_000, 5628) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:0 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn force_bsp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 106_273_000 picoseconds. + Weight::from_parts(108_690_000, 5628) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + fn slash_without_awaiting_top_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `871` + // Estimated: `6172` + // Minimum execution time: 160_594_000 picoseconds. + Weight::from_parts(163_915_000, 6172) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::NextAvailableProviderTopUpExpirationShTick` (r:1 w:1) + /// Proof: `Providers::NextAvailableProviderTopUpExpirationShTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::ProviderTopUpExpirations` (r:1 w:1) + /// Proof: `Providers::ProviderTopUpExpirations` (`max_values`: None, `max_size`: Some(3322), added: 5797, mode: `MaxEncodedLen`) + fn slash_with_awaiting_top_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `871` + // Estimated: `6787` + // Minimum execution time: 128_483_000 picoseconds. + Weight::from_parts(129_763_000, 6787) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::ProviderTopUpExpirations` (r:0 w:1) + /// Proof: `Providers::ProviderTopUpExpirations` (`max_values`: None, `max_size`: Some(3322), added: 5797, mode: `MaxEncodedLen`) + fn top_up_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `758` + // Estimated: `4624` + // Minimum execution time: 115_081_000 picoseconds. + Weight::from_parts(116_579_000, 4624) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::InsolventProviders` (r:2 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn delete_provider_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `853` + // Estimated: `6038` + // Minimum execution time: 80_980_000 picoseconds. + Weight::from_parts(82_589_000, 6038) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) + } + /// Storage: `Providers::InsolventProviders` (r:1 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:22 w:21) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToBuckets` (r:21 w:20) + /// Proof: `Providers::MainStorageProviderIdsToBuckets` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 20]`. + /// The range of component `m` is `[0, 20]`. + fn delete_provider_msp(n: u32, m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1845 + m * (54 ±0) + n * (83 ±0)` + // Estimated: `8186 + m * (2571 ±0) + n * (3598 ±0)` + // Minimum execution time: 184_369_000 picoseconds. + Weight::from_parts(77_759_231, 8186) + // Standard Error: 28_443 + .saturating_add(Weight::from_parts(6_795_099, 0).saturating_mul(n.into())) + // Standard Error: 28_443 + .saturating_add(Weight::from_parts(5_705_653, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) + .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(m.into()))) + .saturating_add(Weight::from_parts(0, 2571).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 3598).saturating_mul(n.into())) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:0) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn stop_all_cycles() -> Weight { + // Proof Size summary in bytes: + // Measured: `549` + // Estimated: `4624` + // Minimum execution time: 27_473_000 picoseconds. + Weight::from_parts(28_240_000, 4624) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:0 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn process_expired_provider_top_up_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `1038` + // Estimated: `6172` + // Minimum execution time: 102_791_000 picoseconds. + Weight::from_parts(105_581_000, 6172) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:0 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + fn process_expired_provider_top_up_msp() -> Weight { + // Proof Size summary in bytes: + // Measured: `775` + // Estimated: `6172` + // Minimum execution time: 83_518_000 picoseconds. + Weight::from_parts(84_579_000, 6172) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } +} diff --git a/operator/runtime/testnet/Cargo.toml b/operator/runtime/testnet/Cargo.toml index 2c40f671..ad02e6dd 100644 --- a/operator/runtime/testnet/Cargo.toml +++ b/operator/runtime/testnet/Cargo.toml @@ -84,6 +84,7 @@ pallet-utility = { workspace = true } pallet-whitelist = { workspace = true } polkadot-primitives = { workspace = true } polkadot-runtime-common = { workspace = true } +k256 = { workspace = true, optional = true } precompile-utils = { workspace = true } scale-info = { workspace = true, features = ["derive", "serde"] } serde = { workspace = true, features = ["derive"] } @@ -360,6 +361,13 @@ runtime-benchmarks = [ "pallet-external-validators-rewards/runtime-benchmarks", "pallet-external-validator-slashes/runtime-benchmarks", "pallet-datahaven-native-transfer/runtime-benchmarks", + # StorageHub pallets + "pallet-nfts/runtime-benchmarks", + "pallet-file-system/runtime-benchmarks", + "pallet-proofs-dealer/runtime-benchmarks", + "pallet-payment-streams/runtime-benchmarks", + "pallet-storage-providers/runtime-benchmarks", + "dep:k256", ] try-runtime = [ diff --git a/operator/runtime/testnet/src/benchmarks.rs b/operator/runtime/testnet/src/benchmarks.rs index 3e59c56f..63b8116c 100644 --- a/operator/runtime/testnet/src/benchmarks.rs +++ b/operator/runtime/testnet/src/benchmarks.rs @@ -27,6 +27,7 @@ frame_benchmarking::define_benchmarks!( // Substrate pallets [pallet_balances, Balances] + [pallet_session, pallet_session_benchmarking::Pallet::] [pallet_identity, Identity] [pallet_im_online, ImOnline] [pallet_multisig, Multisig] @@ -46,6 +47,13 @@ frame_benchmarking::define_benchmarks!( // EVM pallets [pallet_evm, EVM] + // StorageHub pallets + [pallet_nfts, Nfts] + [pallet_file_system, FileSystem] + [pallet_proofs_dealer, ProofsDealer] + [pallet_payment_streams, PaymentStreams] + [pallet_storage_providers, Providers] + // Governance pallets [pallet_collective_technical_committee, TechnicalCommittee] [pallet_collective_treasury_council, TreasuryCouncil] diff --git a/operator/runtime/testnet/src/configs/mod.rs b/operator/runtime/testnet/src/configs/mod.rs index 783c0759..2ea41697 100644 --- a/operator/runtime/testnet/src/configs/mod.rs +++ b/operator/runtime/testnet/src/configs/mod.rs @@ -91,7 +91,6 @@ use datahaven_runtime_common::{ }, time::{EpochDurationInBlocks, SessionsPerEra, DAYS, MILLISECS_PER_BLOCK}, }; -use dhp_bridge::{EigenLayerMessageProcessor, NativeTokenTransferMessageProcessor}; use frame_support::{ derive_impl, dispatch::DispatchClass, @@ -126,7 +125,7 @@ use snowbridge_core::{gwei, meth, AgentIdOf, PricingParameters, Rewards, TokenId use snowbridge_inbound_queue_primitives::RewardLedger; use snowbridge_outbound_queue_primitives::{ v1::{Fee, Message, SendMessage}, - v2::{Command, ConstantGasMeter}, + v2::ConstantGasMeter, SendError, SendMessageFeeProvider, }; use snowbridge_pallet_outbound_queue_v2::OnNewCommitment; @@ -387,7 +386,7 @@ impl pallet_session::Config for Runtime { >; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - type WeightInfo = pallet_session::weights::SubstrateWeight; + type WeightInfo = testnet_weights::pallet_session::WeightInfo; } parameter_types! { @@ -629,7 +628,7 @@ impl pallet_identity::Config for Runtime { type PendingUsernameExpiration = PendingUsernameExpiration; type MaxSuffixLength = MaxSuffixLength; type MaxUsernameLength = MaxUsernameLength; - type WeightInfo = pallet_identity::weights::SubstrateWeight; + type WeightInfo = testnet_weights::pallet_identity::WeightInfo; type UsernameDeposit = UsernameDeposit; type UsernameGracePeriod = UsernameGracePeriod; @@ -1041,8 +1040,8 @@ impl pallet_evm_chain_id::Config for Runtime {} // --- Snowbridge Config Constants & Parameter Types --- parameter_types! { - // Hoodi testnet genesis hash - pub const TestnetGenesisHash: [u8; 32] = hex_literal::hex!("bbe312868b376a3001692a646dd2d7d1e4406380dfd86b98aa8a34d1557c971b"); + // DataHaven testnet genesis hash + pub const TestnetGenesisHash: [u8; 32] = hex_literal::hex!("dbf403d348916fb0694485bc7f9c0d8c53fdf86664ebac019af209c090c3df99"); pub UniversalLocation: InteriorLocation = [ GlobalConsensus(ByGenesis(TestnetGenesisHash::get())) ].into(); @@ -1108,47 +1107,13 @@ impl snowbridge_pallet_system_v2::Config for Runtime { type Helper = (); } -// Fork versions for runtime benchmarks - must match the fixtures for BLS verification to work -// The fixtures are generated with standard testnet fork versions -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub const ChainForkVersions: ForkVersions = ForkVersions { - genesis: Fork { - version: hex_literal::hex!("00000000"), - epoch: 0, - }, - altair: Fork { - version: hex_literal::hex!("01000000"), - epoch: 0, - }, - bellatrix: Fork { - version: hex_literal::hex!("02000000"), - epoch: 0, - }, - capella: Fork { - version: hex_literal::hex!("03000000"), - epoch: 0, - }, - deneb: Fork { - version: hex_literal::hex!("04000000"), - epoch: 0, - }, - electra: Fork { - version: hex_literal::hex!("05000000"), - epoch: 80000000000, - }, - fulu: Fork { - version: hex_literal::hex!("06000000"), - epoch: 90000000000, - }, - }; -} - // For tests, fast-runtime and std configurations we use the mocked fork versions // These match the fork versions used by the local Ethereum network in E2E tests -#[cfg(all( - any(feature = "std", feature = "fast-runtime", test), - not(feature = "runtime-benchmarks") +#[cfg(any( + feature = "std", + feature = "fast-runtime", + feature = "runtime-benchmarks", + test ))] parameter_types! { pub const ChainForkVersions: ForkVersions = ForkVersions { @@ -1278,8 +1243,8 @@ impl snowbridge_pallet_inbound_queue_v2::Config for Runtime { type GatewayAddress = runtime_params::dynamic_params::runtime_config::EthereumGatewayAddress; #[cfg(not(feature = "runtime-benchmarks"))] type MessageProcessor = ( - EigenLayerMessageProcessor, - NativeTokenTransferMessageProcessor, + dhp_bridge::EigenLayerMessageProcessor, + dhp_bridge::NativeTokenTransferMessageProcessor, ); #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = NoOpMessageProcessor; @@ -1749,6 +1714,7 @@ mod tests { use snowbridge_inbound_queue_primitives::v2::{ EthereumAsset, Message as SnowbridgeMessage, MessageProcessor, Payload as SnowPayload, }; + use snowbridge_outbound_queue_primitives::v2::Command; use sp_core::H160; use sp_io::TestExternalities; use xcm_builder::GlobalConsensusConvertsFor; @@ -1875,7 +1841,7 @@ mod tests { message_id: EL_MESSAGE_ID, message: BridgeMessage::V1(InboundCommand::ReceiveValidators { validators: Vec::new(), - external_index: 0, + external_index: 1, }), }; @@ -1950,4 +1916,95 @@ mod tests { assert!(result.is_ok(), "Message from authorized origin should be accepted"); }); } + + /// Test that the ExternalValidatorRewardsAccount is correctly derived from the pallet ID. + /// + /// This verifies that `PalletId(*b"dh/evrew").into_account_truncating()` produces the + /// expected AccountId20 value, which is used in the Rewards Agent ID computation. + #[test] + fn test_external_validator_rewards_account_derivation() { + // Expected account: "modl" (4 bytes) + "dh/evrew" (8 bytes) + zeros (8 bytes) = 20 bytes + // "modl" = 0x6d6f646c + // "dh/evrew" = 0x64682f6576726577 + // Result = 0x6d6f646c64682f65767265770000000000000000 + let expected_account = AccountId::from(hex_literal::hex!( + "6d6f646c64682f65767265770000000000000000" + )); + + let actual_account = ExternalValidatorRewardsAccount::get(); + + assert_eq!( + actual_account, expected_account, + "ExternalValidatorRewardsAccount must be derived correctly from PalletId 'dh/evrew'" + ); + } + + /// Test that the Rewards Agent ID (used for Snowbridge outbound messages from the rewards pallet) + /// is correctly computed from the chain's genesis hash and the ExternalValidatorRewardsAccount. + /// + /// This test verifies the value that should be set as `RewardsAgentOrigin` in runtime parameters + /// and as `rewardsMessageOrigin` in the AVS contract configuration. + /// + /// The Agent ID is computed following Snowbridge's pattern for GlobalConsensus locations: + /// blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), compact_len, "AccountKey20", account_key)) + /// + /// Note: Standard `AgentIdOf` doesn't support direct AccountKey20 without a Parachain junction, + /// so we compute the hash directly here. + #[test] + fn test_rewards_agent_id_computation() { + use codec::Encode; + use sp_core::H256; + use sp_io::hashing::blake2_256; + use xcm::prelude::NetworkId; + + // Use the TestnetGenesisHash parameter + let genesis_hash: [u8; 32] = TestnetGenesisHash::get(); + + // Get the rewards pallet account (derived from PalletId "dh/evrew") + let rewards_account: [u8; 20] = ExternalValidatorRewardsAccount::get().into(); + + // Build the location description following Snowbridge's encoding pattern: + // ("GlobalConsensus", ByGenesis(genesis_hash), compact_len(interior), "AccountKey20", account_key) + // + // This matches the pattern in snowbridge_core::location::DescribeGlobalPrefix + // combined with DescribeTokenTerminal for AccountKey20. + + // Interior description: "AccountKey20" + account_key (no length prefix for fixed arrays) + let interior: Vec = (b"AccountKey20", rewards_account).encode(); + + // Full encoding: "GlobalConsensus" + NetworkId::ByGenesis(genesis) + interior + let encoded: Vec = ( + b"GlobalConsensus", + NetworkId::ByGenesis(genesis_hash), + interior, + ) + .encode(); + + // Hash with blake2_256 + let computed_agent_id = H256(blake2_256(&encoded)); + + // Expected Agent ID - this value must match RewardsAgentOrigin in runtime_params.rs + // If this test fails, update RewardsAgentOrigin to match the computed value. + let expected_agent_id = H256(hex_literal::hex!( + "d0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215" + )); + + assert_eq!( + computed_agent_id, + expected_agent_id, + "Computed Rewards Agent ID must match expected value.\n\ + This value should be set as:\n\ + - RewardsAgentOrigin in runtime_params.rs\n\ + - rewardsMessageOrigin in AVS contract config\n\ + \n\ + Rewards account: 0x{}\n\ + Genesis hash: 0x{}\n\ + Computed: {:?}\n\ + Expected: {:?}", + hex::encode(rewards_account), + hex::encode(genesis_hash), + computed_agent_id, + expected_agent_id + ); + } } diff --git a/operator/runtime/testnet/src/configs/runtime_params.rs b/operator/runtime/testnet/src/configs/runtime_params.rs index 58ef3be2..bc218f6c 100644 --- a/operator/runtime/testnet/src/configs/runtime_params.rs +++ b/operator/runtime/testnet/src/configs/runtime_params.rs @@ -49,10 +49,14 @@ pub mod dynamic_params { #[codec(index = 3)] #[allow(non_upper_case_globals)] - /// The RewardsAgentOrigin is the hash of the string "external_validators_rewards" - /// TODO: Decide which agent origin we want to use. Currently for testing it's the zero hash + /// The RewardsAgentOrigin is the Agent ID for the rewards pallet's outbound Snowbridge messages. + /// Computed as: blake2_256(SCALE_ENCODE("GlobalConsensus", ByGenesis(genesis_hash), interior)) + /// where interior = SCALE_ENCODE("AccountKey20", ExternalValidatorRewardsAccount) + /// + /// For testnet with genesis hash 0xdbf403d348916fb0694485bc7f9c0d8c53fdf86664ebac019af209c090c3df99 + /// and rewards account 0x6d6f646c64682f65767265770000000000000000 (from PalletId "dh/evrew"): pub static RewardsAgentOrigin: H256 = H256::from_slice(&hex!( - "c505dfb2df107d106d08bd0f1a0acd10052ca9aa078629a4ccfd0c90c6e69b65" + "d0d6dbd1ffb401ef613f00e93cd5061ecec03ae35d2f820cd6754a5b5f020215" )); // Proportion of fees allocated to the Treasury (remainder are burned). @@ -129,9 +133,9 @@ pub mod dynamic_params { /// /// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] ) /// - /// 500 = 50 + u * (e ^ (1 - 0.95) - 1) - /// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777 - pub static UpperExponentFactor: u32 = 8777; + /// 500 GIGAWEI = 50 GIGAWEI + u * (e ^ (1 - 0.95) - 1) + /// u = (500 GIGAWEI - 50 GIGAWEI) / (e ^ (1 - 0.95) - 1) ≈ 8,776,874,921,880 + pub static UpperExponentFactor: Balance = 8_776_874_921_880; #[codec(index = 15)] #[allow(non_upper_case_globals)] @@ -140,9 +144,9 @@ pub mod dynamic_params { /// /// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 ) /// - /// 10 = 50 - l * (e ^ (0.3 - 0) - 1) - /// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114 - pub static LowerExponentFactor: u32 = 114; + /// 10 GIGAWEI = 50 GIGAWEI - l * (e ^ (0.3 - 0) - 1) + /// l = (50 GIGAWEI - 10 GIGAWEI) / (e ^ (0.3 - 0) - 1) ≈ 114,331,836,540 + pub static LowerExponentFactor: Balance = 114_331_836_540; #[codec(index = 16)] #[allow(non_upper_case_globals)] diff --git a/operator/runtime/testnet/src/configs/storagehub/mod.rs b/operator/runtime/testnet/src/configs/storagehub/mod.rs index ca2f1d30..7717475c 100644 --- a/operator/runtime/testnet/src/configs/storagehub/mod.rs +++ b/operator/runtime/testnet/src/configs/storagehub/mod.rs @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with DataHaven. If not, see . +#[cfg(not(feature = "runtime-benchmarks"))] +use super::HAVE; +#[cfg(feature = "runtime-benchmarks")] +use super::MICROHAVE; use super::{ AccountId, Balance, Balances, BlockNumber, Hash, RuntimeEvent, RuntimeHoldReason, - TreasuryAccount, HAVE, + TreasuryAccount, }; use crate::configs::runtime_params::dynamic_params::runtime_config; use crate::{ @@ -24,6 +28,8 @@ use crate::{ HOURS, }; use core::marker::PhantomData; +#[cfg(feature = "runtime-benchmarks")] +use datahaven_runtime_common::benchmarking::StorageHubBenchmarking; use datahaven_runtime_common::time::{DAYS, MINUTES}; use frame_support::pallet_prelude::DispatchClass; use frame_support::traits::AsEnsureOriginWithArg; @@ -33,7 +39,7 @@ use frame_support::{ weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; -use frame_system::{EnsureRoot, EnsureSigned}; +use frame_system::EnsureSigned; use num_bigint::BigUint; use pallet_nfts::PalletFeatures; use polkadot_runtime_common::prod_or_fast; @@ -68,6 +74,7 @@ pub type StorageProofsMerkleTrieLayout = LayoutV1; pub type Hashing = BlakeTwo256; /****** NFTs pallet ******/ +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const CollectionDeposit: Balance = 100 * HAVE; pub const ItemDeposit: Balance = 1 * HAVE; @@ -80,6 +87,19 @@ parameter_types! { pub const MaxAttributesPerCall: u32 = 10; pub Features: PalletFeatures = PalletFeatures::all_enabled(); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const CollectionDeposit: Balance = 100 * MICROHAVE; + pub const ItemDeposit: Balance = 1 * MICROHAVE; + pub const MetadataDepositBase: Balance = 10 * MICROHAVE; + pub const MetadataDepositPerByte: Balance = 1 * MICROHAVE; + pub const ApprovalsLimit: u32 = 20; + pub const ItemAttributesApprovalsLimit: u32 = 20; + pub const MaxTips: u32 = 10; + pub const MaxDeadlineDuration: BlockNumber = 12 * 30 * DAYS; + pub const MaxAttributesPerCall: u32 = 10; + pub Features: PalletFeatures = PalletFeatures::all_enabled(); +} impl pallet_nfts::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -104,11 +124,67 @@ impl pallet_nfts::Config for Runtime { type Features = Features; type OffchainSignature = Signature; type OffchainPublic = ::Signer; - type WeightInfo = pallet_nfts::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_nfts::WeightInfo; type Locker = (); + #[cfg(feature = "runtime-benchmarks")] + type Helper = benchmark_helpers::NftHelper; } /****** ****** ****** ******/ +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmark_helpers { + use crate::{AccountId, Signature}; + use k256::ecdsa::SigningKey; + use sp_runtime::traits::{IdentifyAccount, Verify}; + use sp_runtime::MultiSignature; + + const BENCH_SIGNING_KEY: [u8; 32] = [1u8; 32]; + + fn bench_signing_key() -> SigningKey { + SigningKey::from_bytes(&BENCH_SIGNING_KEY.into()) + .expect("benchmark signing key is valid; qed") + } + + /// Benchmark helper for NFTs pallet + pub struct NftHelper; + + impl pallet_nfts::BenchmarkHelper::Signer, AccountId, Signature> + for NftHelper + { + fn collection(i: u16) -> u32 { + i.into() + } + + fn item(i: u16) -> u32 { + i.into() + } + + fn signer() -> (::Signer, AccountId) { + let signing_key = bench_signing_key(); + let verifying_key = signing_key.verifying_key(); + let encoded = verifying_key.to_encoded_point(true); + let public = sp_core::ecdsa::Public::from_full(encoded.as_bytes()) + .expect("encoded point is a valid compressed secp256k1 key; qed"); + let public_key: ::Signer = public.into(); + let account: AccountId = public_key.clone().into_account(); + (public_key, account) + } + + fn sign(_public: &::Signer, message: &[u8]) -> Signature { + // Sign using Ethereum-style secp256k1 over keccak256(message). + let digest = sp_io::hashing::keccak_256(message); + let (sig, recovery_id) = bench_signing_key() + .sign_prehash_recoverable(&digest) + .expect("signing with fixed secret key never fails; qed"); + let mut sig_bytes = [0u8; 65]; + sig_bytes[..64].copy_from_slice(&sig.to_bytes()); + sig_bytes[64] = recovery_id.to_byte(); + let sig = sp_core::ecdsa::Signature::from_raw(sig_bytes); + Signature::from(MultiSignature::Ecdsa(sig)) + } + } +} + /****** Relay Randomness pallet ******/ impl pallet_randomness::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -151,6 +227,7 @@ impl sp_runtime::traits::BlockNumberProvider for BlockNumberGetter { /****** ****** ****** ******/ /****** Storage Providers pallet ******/ +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const SpMinDeposit: Balance = 100 * HAVE; pub const BucketDeposit: Balance = 100 * HAVE; @@ -159,10 +236,47 @@ parameter_types! { // TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues) // pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const SpMinDeposit: Balance = StorageHubBenchmarking::SP_MIN_DEPOSIT; + pub const BucketDeposit: Balance = StorageHubBenchmarking::BUCKET_DEPOSIT; + pub const BspSignUpLockPeriod: BlockNumber = 90 * DAYS; // ~3 months + pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * HOURS, 2 * MINUTES); + // TODO: If the next line is uncommented (which should be eventually, replacing the line above), compilation breaks (most likely because of mismatched dependency issues) + // pub const MaxBlocksForRandomness: BlockNumber = prod_or_fast!(2 * runtime_constants::time::EPOCH_DURATION_IN_SLOTS, 2 * MINUTES); +} + +#[cfg(feature = "runtime-benchmarks")] +pub struct StorageHubTreasuryAccount; +#[cfg(feature = "runtime-benchmarks")] +impl Get for StorageHubTreasuryAccount { + fn get() -> AccountId { + let account = TreasuryAccount::get(); + StorageHubBenchmarking::ensure_treasury_account::(account) + } +} + +// Benchmark helpers for Storage Providers pallet. +#[cfg(feature = "runtime-benchmarks")] +pub struct ProvidersBenchmarkHelpers; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_storage_providers::benchmarking::BenchmarkHelpers + for ProvidersBenchmarkHelpers +{ + type ProviderId = ::ProviderId; + + fn set_accrued_failed_proofs(provider_id: Self::ProviderId, value: u32) { + pallet_proofs_dealer::SlashableProviders::::insert(provider_id, value); + } + + fn get_accrued_failed_proofs(provider_id: Self::ProviderId) -> u32 { + pallet_proofs_dealer::SlashableProviders::::get(provider_id).unwrap_or(0) + } +} impl pallet_storage_providers::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_storage_providers::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_storage_providers::WeightInfo; type ProvidersRandomness = pallet_randomness::RandomnessFromOneEpochAgo; type PaymentStreams = PaymentStreams; type ProofDealer = ProofsDealer; @@ -188,7 +302,10 @@ impl pallet_storage_providers::Config for Runtime { type ProvidersProofSubmitters = ProofsDealer; type ReputationWeightType = u32; type StorageHubTickGetter = ProofsDealer; + #[cfg(not(feature = "runtime-benchmarks"))] type Treasury = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type Treasury = StorageHubTreasuryAccount; type SpMinDeposit = SpMinDeposit; type SpMinCapacity = ConstU64<2>; type DepositPerData = ConstU128<2>; @@ -208,6 +325,8 @@ impl pallet_storage_providers::Config for Runtime { type ZeroSizeBucketFixedRate = runtime_config::ZeroSizeBucketFixedRate; type ProviderTopUpTtl = runtime_config::ProviderTopUpTtl; type MaxExpiredItemsInBlock = ConstU32<100>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelpers = ProvidersBenchmarkHelpers; } pub struct StorageDataUnitAndBalanceConverter; @@ -240,7 +359,7 @@ parameter_types! { impl pallet_payment_streams::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_payment_streams::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_payment_streams::WeightInfo; type NativeBalance = Balances; type ProvidersPallet = Providers; type RuntimeHoldReason = RuntimeHoldReason; @@ -250,7 +369,10 @@ impl pallet_payment_streams::Config for Runtime { type BlockNumberToBalance = BlockNumberToBalance; type ProvidersProofSubmitters = ProofsDealer; type TreasuryCutCalculator = LinearThenPowerOfTwoTreasuryCutCalculator; + #[cfg(not(feature = "runtime-benchmarks"))] type TreasuryAccount = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type TreasuryAccount = StorageHubTreasuryAccount; type MaxUsersToCharge = ConstU32<10>; type BaseDeposit = ConstU128<10>; } @@ -279,6 +401,14 @@ const MAX_CUSTOM_CHALLENGES_PER_BLOCK: u32 = 10; const TOTAL_MAX_CHALLENGES_PER_BLOCK: u32 = RANDOM_CHALLENGES_PER_BLOCK + MAX_CUSTOM_CHALLENGES_PER_BLOCK; +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BenchmarkStakeToChallengePeriod: Balance = + StorageHubBenchmarking::STAKE_TO_CHALLENGE_PERIOD; + pub const BenchmarkCheckpointChallengePeriod: BlockNumber = + StorageHubBenchmarking::CHECKPOINT_CHALLENGE_PERIOD; +} + parameter_types! { pub const RandomChallengesPerBlock: u32 = RANDOM_CHALLENGES_PER_BLOCK; pub const MaxCustomChallengesPerBlock: u32 = MAX_CUSTOM_CHALLENGES_PER_BLOCK; @@ -293,7 +423,7 @@ parameter_types! { impl pallet_proofs_dealer::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_proofs_dealer::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_proofs_dealer::WeightInfo; type ProvidersPallet = Providers; type NativeBalance = Balances; type MerkleTrieHash = Hash; @@ -306,29 +436,50 @@ impl pallet_proofs_dealer::Config for Runtime { { shp_constants::FILE_SIZE_TO_CHALLENGES }, >; type StakeToBlockNumber = SaturatingBalanceToBlockNumber; + #[cfg(feature = "runtime-benchmarks")] + type RandomChallengesPerBlock = ConstU32<0>; + #[cfg(not(feature = "runtime-benchmarks"))] type RandomChallengesPerBlock = RandomChallengesPerBlock; + #[cfg(feature = "runtime-benchmarks")] + type MaxCustomChallengesPerBlock = TotalMaxChallengesPerBlock; + #[cfg(not(feature = "runtime-benchmarks"))] type MaxCustomChallengesPerBlock = MaxCustomChallengesPerBlock; type MaxSubmittersPerTick = MaxSubmittersPerTick; type TargetTicksStorageOfSubmitters = TargetTicksStorageOfSubmitters; type ChallengeHistoryLength = ChallengeHistoryLength; type ChallengesQueueLength = ChallengesQueueLength; + #[cfg(not(feature = "runtime-benchmarks"))] type CheckpointChallengePeriod = runtime_config::CheckpointChallengePeriod; + #[cfg(feature = "runtime-benchmarks")] + type CheckpointChallengePeriod = BenchmarkCheckpointChallengePeriod; type ChallengesFee = ChallengesFee; type PriorityChallengesFee = PriorityChallengesFee; + #[cfg(not(feature = "runtime-benchmarks"))] type Treasury = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type Treasury = StorageHubTreasuryAccount; // TODO: Once the client logic to keep track of CR randomness deadlines and execute their submissions is implemented // AND after the chain has been live for enough time to have enough providers to avoid the commit-reveal randomness being // gameable, the randomness provider should be CrRandomness type RandomnessProvider = pallet_randomness::ParentBlockRandomness; + #[cfg(not(feature = "runtime-benchmarks"))] type StakeToChallengePeriod = runtime_config::StakeToChallengePeriod; + #[cfg(feature = "runtime-benchmarks")] + type StakeToChallengePeriod = BenchmarkStakeToChallengePeriod; type MinChallengePeriod = runtime_config::MinChallengePeriod; type ChallengeTicksTolerance = ChallengeTicksTolerance; type BlockFullnessPeriod = ChallengeTicksTolerance; // We purposely set this to `ChallengeTicksTolerance` so that spamming of the chain is evaluated for the same blocks as the tolerance BSPs are given. type BlockFullnessHeadroom = BlockFullnessHeadroom; type MinNotFullBlocksRatio = MinNotFullBlocksRatio; type MaxSlashableProvidersPerTick = MaxSlashableProvidersPerTick; - type ChallengeOrigin = EnsureRoot; - type PriorityChallengeOrigin = EnsureRoot; + #[cfg(not(feature = "runtime-benchmarks"))] + type ChallengeOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ChallengeOrigin = EnsureSigned; + #[cfg(not(feature = "runtime-benchmarks"))] + type PriorityChallengeOrigin = frame_system::EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type PriorityChallengeOrigin = EnsureSigned; } // Converter from the Balance type to the BlockNumber type for math. @@ -452,12 +603,24 @@ impl Get for MaxSlashableProvidersPerTick { type ThresholdType = u32; pub type ReplicationTargetType = u32; +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const BaseStorageRequestCreationDeposit: Balance = 1 * HAVE; pub const FileDeletionRequestCreationDeposit: Balance = 1 * HAVE; pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold); pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold); } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BaseStorageRequestCreationDeposit: Balance = 1 * MICROHAVE; + pub const FileDeletionRequestCreationDeposit: Balance = 1 * MICROHAVE; + pub const FileSystemStorageRequestCreationHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::StorageRequestCreationHold); + pub const FileSystemFileDeletionRequestHoldReason: RuntimeHoldReason = RuntimeHoldReason::FileSystem(pallet_file_system::HoldReason::FileDeletionRequestHold); +} +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const BenchmarkBspStopStoringFilePenalty: Balance = 1 * MICROHAVE; +} // Converts a given signed message in a EIP-191 compliant message bytes to verify. /// EIP-191: https://eips.ethereum.org/EIPS/eip-191 @@ -480,7 +643,7 @@ impl shp_traits::MessageAdapter for Eip191Adapter { impl pallet_file_system::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_file_system::weights::SubstrateWeight; + type WeightInfo = crate::weights::pallet_file_system::WeightInfo; type Providers = Providers; type ProofDealer = ProofsDealer; type PaymentStreams = PaymentStreams; @@ -500,8 +663,14 @@ impl pallet_file_system::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type Nfts = Nfts; type CollectionInspector = BucketNfts; + #[cfg(not(feature = "runtime-benchmarks"))] type BspStopStoringFilePenalty = runtime_config::BspStopStoringFilePenalty; + #[cfg(feature = "runtime-benchmarks")] + type BspStopStoringFilePenalty = BenchmarkBspStopStoringFilePenalty; + #[cfg(not(feature = "runtime-benchmarks"))] type TreasuryAccount = TreasuryAccount; + #[cfg(feature = "runtime-benchmarks")] + type TreasuryAccount = StorageHubTreasuryAccount; type MaxBatchConfirmStorageRequests = ConstU32<100>; type MaxFilePathSize = ConstU32<512u32>; type MaxPeerIdSize = ConstU32<100>; diff --git a/operator/runtime/testnet/src/genesis_config_presets.rs b/operator/runtime/testnet/src/genesis_config_presets.rs index d40eb073..e568f266 100644 --- a/operator/runtime/testnet/src/genesis_config_presets.rs +++ b/operator/runtime/testnet/src/genesis_config_presets.rs @@ -265,7 +265,7 @@ pub fn dorothy() -> AccountId { } pub fn ethan() -> AccountId { - AccountId::from(hex!("Ff64d3F6efE2317EE2807d2235B1ac2AA69d9E87")) + AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")) } pub fn frank() -> AccountId { diff --git a/operator/runtime/testnet/src/lib.rs b/operator/runtime/testnet/src/lib.rs index 46a777a5..0f1d0dd5 100644 --- a/operator/runtime/testnet/src/lib.rs +++ b/operator/runtime/testnet/src/lib.rs @@ -142,7 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 1000, + spec_version: 1300, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -201,7 +201,7 @@ parameter_types! { parameter_types! { // TODO: Change ED to 1 after upgrade to Polkadot SDK stable2503 // cfr. https://github.com/paritytech/polkadot-sdk/pull/7379 - pub const ExistentialDeposit: Balance = 100; + pub const ExistentialDeposit: Balance = 1; } /// The version information used to identify this runtime when compiled natively. @@ -972,6 +972,7 @@ impl_runtime_apis! { use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} + impl pallet_session_benchmarking::Config for Runtime {} impl baseline::Config for Runtime {} use frame_support::traits::WhitelistedStorageKeys; @@ -1263,6 +1264,9 @@ impl_runtime_apis! { ) -> Vec { FileSystem::query_pending_bsp_confirm_storage_requests(bsp_id, file_keys) } + fn get_max_batch_confirm_storage_requests() -> BlockNumber { + FileSystem::get_max_batch_confirm_storage_requests() + } } impl pallet_payment_streams_runtime_api::PaymentStreamsApi, Balance, AccountId> for Runtime { diff --git a/operator/runtime/testnet/src/weights/mod.rs b/operator/runtime/testnet/src/weights/mod.rs index f1d772a1..979467af 100644 --- a/operator/runtime/testnet/src/weights/mod.rs +++ b/operator/runtime/testnet/src/weights/mod.rs @@ -35,19 +35,25 @@ pub mod pallet_babe; pub mod pallet_balances; pub mod pallet_beefy_mmr; pub mod pallet_evm; +pub mod pallet_file_system; pub mod pallet_grandpa; -pub mod pallet_randomness; -//pub mod pallet_identity; +pub mod pallet_identity; pub mod pallet_im_online; pub mod pallet_message_queue; pub mod pallet_migrations; pub mod pallet_mmr; pub mod pallet_multisig; +pub mod pallet_nfts; pub mod pallet_parameters; +pub mod pallet_payment_streams; pub mod pallet_preimage; +pub mod pallet_proofs_dealer; pub mod pallet_proxy; +pub mod pallet_randomness; pub mod pallet_safe_mode; pub mod pallet_scheduler; +pub mod pallet_session; +pub mod pallet_storage_providers; pub mod pallet_sudo; pub mod pallet_timestamp; pub mod pallet_transaction_payment; diff --git a/operator/runtime/testnet/src/weights/pallet_file_system.rs b/operator/runtime/testnet/src/weights/pallet_file_system.rs new file mode 100644 index 00000000..4a2a2050 --- /dev/null +++ b/operator/runtime/testnet/src/weights/pallet_file_system.rs @@ -0,0 +1,5 @@ +//! Weights for `pallet_file_system`. +//! +//! Generated weights should overwrite this file. + +pub use pallet_file_system::weights::SubstrateWeight as WeightInfo; diff --git a/operator/runtime/testnet/src/weights/pallet_nfts.rs b/operator/runtime/testnet/src/weights/pallet_nfts.rs new file mode 100644 index 00000000..2e594b5b --- /dev/null +++ b/operator/runtime/testnet/src/weights/pallet_nfts.rs @@ -0,0 +1,724 @@ + + +//! Autogenerated weights for `pallet_nfts` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2025-11-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-testnet-runtime/datahaven_testnet_runtime.compact.compressed.wasm +// --pallet +// pallet_nfts +// --extrinsic +// +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/testnet/src/weights/pallet_nfts.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_nfts`. +pub struct WeightInfo(PhantomData); +impl pallet_nfts::WeightInfo for WeightInfo { + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `271` + // Estimated: `3537` + // Minimum execution time: 47_561_000 picoseconds. + Weight::from_parts(48_583_000, 3537) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::NextCollectionId` (r:1 w:1) + /// Proof: `Nfts::NextCollectionId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:0 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn force_create() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3537` + // Minimum execution time: 25_742_000 picoseconds. + Weight::from_parts(26_196_000, 3537) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:1) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1000 w:1000) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:0 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:1) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// The range of component `m` is `[0, 1000]`. + /// The range of component `c` is `[0, 1000]`. + /// The range of component `a` is `[0, 1000]`. + fn destroy(_m: u32, _c: u32, a: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `32179 + a * (366 ±0)` + // Estimated: `2523990 + a * (2930 ±0)` + // Minimum execution time: 1_304_607_000 picoseconds. + Weight::from_parts(3_891_413_864, 2523990) + // Standard Error: 30_112 + .saturating_add(Weight::from_parts(7_300_422, 0).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(1004_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into()))) + .saturating_add(T::DbWeight::get().writes(1005_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(a.into())) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + fn mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `418` + // Estimated: `4062` + // Minimum execution time: 68_983_000 picoseconds. + Weight::from_parts(69_802_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + fn force_mint() -> Weight { + // Proof Size summary in bytes: + // Measured: `418` + // Estimated: `4062` + // Minimum execution time: 65_803_000 picoseconds. + Weight::from_parts(67_191_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:0) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:0 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn burn() -> Weight { + // Proof Size summary in bytes: + // Measured: `526` + // Estimated: `4062` + // Minimum execution time: 74_085_000 picoseconds. + Weight::from_parts(75_919_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `555` + // Estimated: `4062` + // Minimum execution time: 56_531_000 picoseconds. + Weight::from_parts(57_676_000, 4062) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:5000 w:5000) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// The range of component `i` is `[0, 5000]`. + fn redeposit(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `750 + i * (83 ±0)` + // Estimated: `3538 + i * (3072 ±0)` + // Minimum execution time: 18_545_000 picoseconds. + Weight::from_parts(18_987_000, 3538) + // Standard Error: 11_750 + .saturating_add(Weight::from_parts(23_672_529, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) + .saturating_add(Weight::from_parts(0, 3072).saturating_mul(i.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn lock_item_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 24_040_000 picoseconds. + Weight::from_parts(24_947_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn unlock_item_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 23_941_000 picoseconds. + Weight::from_parts(24_858_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn lock_collection() -> Weight { + // Proof Size summary in bytes: + // Measured: `327` + // Estimated: `3538` + // Minimum execution time: 19_598_000 picoseconds. + Weight::from_parts(20_471_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn transfer_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `524` + // Estimated: `3581` + // Minimum execution time: 35_013_000 picoseconds. + Weight::from_parts(36_104_000, 3581) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:4) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + fn set_team() -> Weight { + // Proof Size summary in bytes: + // Measured: `344` + // Estimated: `6054` + // Minimum execution time: 48_777_000 picoseconds. + Weight::from_parts(50_672_000, 6054) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionAccount` (r:0 w:2) + /// Proof: `Nfts::CollectionAccount` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn force_collection_owner() -> Weight { + // Proof Size summary in bytes: + // Measured: `298` + // Estimated: `3537` + // Minimum execution time: 20_455_000 picoseconds. + Weight::from_parts(21_229_000, 3537) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:0 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn force_collection_config() -> Weight { + // Proof Size summary in bytes: + // Measured: `276` + // Estimated: `3537` + // Minimum execution time: 16_326_000 picoseconds. + Weight::from_parts(16_897_000, 3537) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn lock_item_properties() -> Weight { + // Proof Size summary in bytes: + // Measured: `423` + // Estimated: `3522` + // Minimum execution time: 22_519_000 picoseconds. + Weight::from_parts(23_274_000, 3522) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + fn set_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `514` + // Estimated: `3920` + // Minimum execution time: 69_247_000 picoseconds. + Weight::from_parts(70_996_000, 3920) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + fn force_set_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `331` + // Estimated: `3920` + // Minimum execution time: 33_077_000 picoseconds. + Weight::from_parts(33_810_000, 3920) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Attribute` (r:1 w:1) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + fn clear_attribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `958` + // Estimated: `3920` + // Minimum execution time: 63_523_000 picoseconds. + Weight::from_parts(64_779_000, 3920) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + fn approve_item_attributes() -> Weight { + // Proof Size summary in bytes: + // Measured: `356` + // Estimated: `4062` + // Minimum execution time: 20_686_000 picoseconds. + Weight::from_parts(21_511_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1001 w:1000) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn cancel_item_attributes_approval(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `769 + n * (386 ±0)` + // Estimated: `4062 + n * (2930 ±0)` + // Minimum execution time: 33_029_000 picoseconds. + Weight::from_parts(33_938_000, 4062) + // Standard Error: 3_029 + .saturating_add(Weight::from_parts(7_579_917, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + fn set_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `514` + // Estimated: `3800` + // Minimum execution time: 56_219_000 picoseconds. + Weight::from_parts(57_548_000, 3800) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn clear_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `824` + // Estimated: `3800` + // Minimum execution time: 53_360_000 picoseconds. + Weight::from_parts(54_827_000, 3800) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + fn set_collection_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `373` + // Estimated: `3759` + // Minimum execution time: 50_851_000 picoseconds. + Weight::from_parts(52_322_000, 3759) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionMetadataOf` (r:1 w:1) + /// Proof: `Nfts::CollectionMetadataOf` (`max_values`: None, `max_size`: Some(294), added: 2769, mode: `MaxEncodedLen`) + fn clear_collection_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `691` + // Estimated: `3759` + // Minimum execution time: 50_304_000 picoseconds. + Weight::from_parts(51_259_000, 3759) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn approve_transfer() -> Weight { + // Proof Size summary in bytes: + // Measured: `385` + // Estimated: `4062` + // Minimum execution time: 24_516_000 picoseconds. + Weight::from_parts(25_110_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn cancel_approval() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `4062` + // Minimum execution time: 20_404_000 picoseconds. + Weight::from_parts(21_281_000, 4062) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn clear_all_transfer_approvals() -> Weight { + // Proof Size summary in bytes: + // Measured: `382` + // Estimated: `4062` + // Minimum execution time: 19_568_000 picoseconds. + Weight::from_parts(20_376_000, 4062) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::OwnershipAcceptance` (r:1 w:1) + /// Proof: `Nfts::OwnershipAcceptance` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn set_accept_ownership() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3505` + // Minimum execution time: 17_232_000 picoseconds. + Weight::from_parts(17_555_000, 3505) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + fn set_collection_max_supply() -> Weight { + // Proof Size summary in bytes: + // Measured: `327` + // Estimated: `3538` + // Minimum execution time: 22_353_000 picoseconds. + Weight::from_parts(22_864_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:1 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:1) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn update_mint_settings() -> Weight { + // Proof Size summary in bytes: + // Measured: `311` + // Estimated: `3538` + // Minimum execution time: 21_008_000 picoseconds. + Weight::from_parts(21_821_000, 3538) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + fn set_price() -> Weight { + // Proof Size summary in bytes: + // Measured: `493` + // Estimated: `4062` + // Minimum execution time: 30_820_000 picoseconds. + Weight::from_parts(31_676_000, 4062) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:1 w:1) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:1 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:2) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn buy_item() -> Weight { + // Proof Size summary in bytes: + // Measured: `655` + // Estimated: `4062` + // Minimum execution time: 67_391_000 picoseconds. + Weight::from_parts(69_020_000, 4062) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// The range of component `n` is `[0, 10]`. + fn pay_tips(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_194_000 picoseconds. + Weight::from_parts(4_693_046, 0) + // Standard Error: 8_482 + .saturating_add(Weight::from_parts(2_570_624, 0).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:2 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:0 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + fn create_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `444` + // Estimated: `7134` + // Minimum execution time: 26_668_000 picoseconds. + Weight::from_parts(27_700_000, 7134) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::PendingSwapOf` (r:1 w:1) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + fn cancel_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `488` + // Estimated: `4062` + // Minimum execution time: 27_612_000 picoseconds. + Weight::from_parts(28_523_000, 4062) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Nfts::Item` (r:2 w:2) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::PendingSwapOf` (r:1 w:2) + /// Proof: `Nfts::PendingSwapOf` (`max_values`: None, `max_size`: Some(71), added: 2546, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:0) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:2 w:0) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:2 w:0) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:4) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemPriceOf` (r:0 w:2) + /// Proof: `Nfts::ItemPriceOf` (`max_values`: None, `max_size`: Some(77), added: 2552, mode: `MaxEncodedLen`) + fn claim_swap() -> Weight { + // Proof Size summary in bytes: + // Measured: `771` + // Estimated: `7134` + // Minimum execution time: 109_691_000 picoseconds. + Weight::from_parts(111_678_000, 7134) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(10_u64)) + } + /// Storage: `Nfts::CollectionRoleOf` (r:2 w:0) + /// Proof: `Nfts::CollectionRoleOf` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Item` (r:1 w:1) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemConfigOf` (r:1 w:1) + /// Proof: `Nfts::ItemConfigOf` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemMetadataOf` (r:1 w:1) + /// Proof: `Nfts::ItemMetadataOf` (`max_values`: None, `max_size`: Some(335), added: 2810, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Account` (r:0 w:1) + /// Proof: `Nfts::Account` (`max_values`: None, `max_size`: Some(76), added: 2551, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn mint_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `580` + // Estimated: `6054 + n * (2930 ±0)` + // Minimum execution time: 158_638_000 picoseconds. + Weight::from_parts(165_550_686, 6054) + // Standard Error: 65_710 + .saturating_add(Weight::from_parts(43_677_181, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } + /// Storage: `Nfts::Item` (r:1 w:0) + /// Proof: `Nfts::Item` (`max_values`: None, `max_size`: Some(597), added: 3072, mode: `MaxEncodedLen`) + /// Storage: `Nfts::ItemAttributesApprovalsOf` (r:1 w:1) + /// Proof: `Nfts::ItemAttributesApprovalsOf` (`max_values`: None, `max_size`: Some(441), added: 2916, mode: `MaxEncodedLen`) + /// Storage: `Nfts::CollectionConfigOf` (r:1 w:0) + /// Proof: `Nfts::CollectionConfigOf` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Collection` (r:1 w:1) + /// Proof: `Nfts::Collection` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Nfts::Attribute` (r:10 w:10) + /// Proof: `Nfts::Attribute` (`max_values`: None, `max_size`: Some(455), added: 2930, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn set_attributes_pre_signed(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `575` + // Estimated: `4062 + n * (2930 ±0)` + // Minimum execution time: 75_427_000 picoseconds. + Weight::from_parts(88_971_257, 4062) + // Standard Error: 91_158 + .saturating_add(Weight::from_parts(42_253_239, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2930).saturating_mul(n.into())) + } +} diff --git a/operator/runtime/testnet/src/weights/pallet_payment_streams.rs b/operator/runtime/testnet/src/weights/pallet_payment_streams.rs new file mode 100644 index 00000000..d094d81d --- /dev/null +++ b/operator/runtime/testnet/src/weights/pallet_payment_streams.rs @@ -0,0 +1,449 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_payment_streams` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-testnet-runtime/datahaven_testnet_runtime.compact.compressed.wasm +// --pallet +// pallet_payment_streams +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/testnet/src/weights/pallet_payment_streams.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_payment_streams`. +pub struct WeightInfo(PhantomData); +impl pallet_payment_streams::weights::WeightInfo for WeightInfo { + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn create_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `523` + // Estimated: `6054` + // Minimum execution time: 108_671_000 picoseconds. + Weight::from_parts(110_483_000, 6054) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn update_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1427` + // Estimated: `12414` + // Minimum execution time: 406_731_000 picoseconds. + Weight::from_parts(416_205_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn delete_fixed_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1304` + // Estimated: `12414` + // Minimum execution time: 294_818_000 picoseconds. + Weight::from_parts(298_194_000, 12414) + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:0) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn create_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `525` + // Estimated: `6054` + // Minimum execution time: 110_206_000 picoseconds. + Weight::from_parts(112_480_000, 6054) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn update_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1387` + // Estimated: `12414` + // Minimum execution time: 350_407_000 picoseconds. + Weight::from_parts(353_687_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn delete_dynamic_rate_payment_stream() -> Weight { + // Proof Size summary in bytes: + // Measured: `1455` + // Estimated: `12414` + // Minimum execution time: 407_867_000 picoseconds. + Weight::from_parts(423_394_000, 12414) + .saturating_add(T::DbWeight::get().reads(22_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:3 w:3) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn charge_payment_streams() -> Weight { + // Proof Size summary in bytes: + // Measured: `1441` + // Estimated: `12414` + // Minimum execution time: 337_670_000 picoseconds. + Weight::from_parts(343_494_000, 12414) + .saturating_add(T::DbWeight::get().reads(21_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:10 w:10) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:10 w:10) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:10 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:12 w:12) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 10]`. + fn charge_multiple_users_payment_streams(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1122 + n * (331 ±0)` + // Estimated: `12414 + n * (2604 ±0)` + // Minimum execution time: 20_398_000 picoseconds. + Weight::from_parts(45_361_517, 12414) + // Standard Error: 164_730 + .saturating_add(Weight::from_parts(296_339_119, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2604).saturating_mul(n.into())) + } + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1001 w:1001) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:0) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:999 w:999) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:999 w:999) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:999 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:999 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:4 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:999 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:1) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 1000]`. + fn pay_outstanding_debt(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1422 + n * (644 ±0)` + // Estimated: `12414 + n * (3634 ±0)` + // Minimum execution time: 379_144_000 picoseconds. + Weight::from_parts(384_440_000, 12414) + // Standard Error: 164_472 + .saturating_add(Weight::from_parts(287_945_137, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(11_u64)) + .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(4_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3634).saturating_mul(n.into())) + } + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:1) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:0) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::RegisteredUsers` (r:1 w:0) + /// Proof: `PaymentStreams::RegisteredUsers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + fn clear_insolvent_flag() -> Weight { + // Proof Size summary in bytes: + // Measured: `231` + // Estimated: `3505` + // Minimum execution time: 22_622_000 picoseconds. + Weight::from_parts(23_508_000, 3505) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:1) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + fn price_index_update() -> Weight { + // Proof Size summary in bytes: + // Measured: `116` + // Estimated: `1501` + // Minimum execution time: 5_924_000 picoseconds. + Weight::from_parts(6_148_000, 1501) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `PaymentStreams::OnPollTicker` (r:1 w:1) + /// Proof: `PaymentStreams::OnPollTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn tick_update() -> Weight { + // Proof Size summary in bytes: + // Measured: `114` + // Estimated: `1489` + // Minimum execution time: 4_037_000 picoseconds. + Weight::from_parts(4_180_000, 1489) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastSubmittersTickRegistered` (r:1 w:1) + /// Proof: `PaymentStreams::LastSubmittersTickRegistered` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:0) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::AccumulatedPriceIndex` (r:1 w:0) + /// Proof: `PaymentStreams::AccumulatedPriceIndex` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:244 w:244) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 244]`. + fn update_providers_last_chargeable_info(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `270 + n * (32 ±0)` + // Estimated: `11295 + n * (2543 ±0)` + // Minimum execution time: 12_833_000 picoseconds. + Weight::from_parts(14_336_361, 11295) + // Standard Error: 5_031 + .saturating_add(Weight::from_parts(6_893_894, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2543).saturating_mul(n.into())) + } +} diff --git a/operator/runtime/testnet/src/weights/pallet_proofs_dealer.rs b/operator/runtime/testnet/src/weights/pallet_proofs_dealer.rs new file mode 100644 index 00000000..7ad738bf --- /dev/null +++ b/operator/runtime/testnet/src/weights/pallet_proofs_dealer.rs @@ -0,0 +1,326 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_proofs_dealer` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-testnet-runtime/datahaven_testnet_runtime.compact.compressed.wasm +// --pallet +// pallet_proofs_dealer +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/testnet/src/weights/pallet_proofs_dealer.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_proofs_dealer`. +pub struct WeightInfo(PhantomData); +impl pallet_proofs_dealer::weights::WeightInfo for WeightInfo { + /// Storage: `ProofsDealer::ChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + fn challenge() -> Weight { + // Proof Size summary in bytes: + // Measured: `41` + // Estimated: `4687` + // Minimum execution time: 11_486_000 picoseconds. + Weight::from_parts(11_900_000, 4687) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:2 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:1 w:0) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:5 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:2) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 20]`. + fn submit_proof_no_checkpoint_challenges_key_proofs(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2070` + // Estimated: `15270` + // Minimum execution time: 2_174_837_000 picoseconds. + Weight::from_parts(2_059_384_726, 15270) + // Standard Error: 314_390 + .saturating_add(Weight::from_parts(135_797_182, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(30_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:1 w:0) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:1 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:2) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::UsersWithoutFunds` (r:1 w:0) + /// Proof: `PaymentStreams::UsersWithoutFunds` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:1) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:2 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:2 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:1 w:0) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::LastChargeableInfo` (r:1 w:0) + /// Proof: `PaymentStreams::LastChargeableInfo` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:0) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (r:1 w:0) + /// Proof: `PaymentStreams::CurrentPricePerGigaUnitPerTick` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// The range of component `n` is `[21, 40]`. + fn submit_proof_with_checkpoint_challenges_key_proofs(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2070` + // Estimated: `20676` + // Minimum execution time: 4_570_889_000 picoseconds. + Weight::from_parts(4_000_730_198, 20676) + // Standard Error: 951_176 + .saturating_add(Weight::from_parts(35_912_979, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(39_u64)) + .saturating_add(T::DbWeight::get().writes(11_u64)) + } + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestParentBlockRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestParentBlockRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:1 w:0) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckForSlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::TickToCheckForSlashableProviders` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:1001 w:2000) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1000 w:1000) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1000 w:1000) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1000 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1000 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToChallengesSeed` (r:0 w:1) + /// Proof: `ProofsDealer::TickToChallengesSeed` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 1000]`. + fn new_challenges_round(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1155 + n * (271 ±0)` + // Estimated: `6172 + n * (3634 ±0)` + // Minimum execution time: 29_687_000 picoseconds. + Weight::from_parts(30_010_000, 6172) + // Standard Error: 49_079 + .saturating_add(Weight::from_parts(40_156_766, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes((4_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3634).saturating_mul(n.into())) + } + /// Storage: `ProofsDealer::PriorityChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::PriorityChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3302), added: 3797, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesQueue` (r:1 w:1) + /// Proof: `ProofsDealer::ChallengesQueue` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::LastCheckpointTick` (r:1 w:1) + /// Proof: `ProofsDealer::LastCheckpointTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToCheckpointChallenges` (r:0 w:2) + /// Proof: `ProofsDealer::TickToCheckpointChallenges` (`max_values`: None, `max_size`: Some(681), added: 3156, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 20]`. + fn new_checkpoint_challenge_round(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `65 + n * (32 ±0)` + // Estimated: `4787` + // Minimum execution time: 14_023_000 picoseconds. + Weight::from_parts(16_003_551, 4787) + // Standard Error: 3_466 + .saturating_add(Weight::from_parts(429_621, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `ProofsDealer::PastBlocksStatus` (r:1 w:1) + /// Proof: `ProofsDealer::PastBlocksStatus` (`max_values`: Some(1), `max_size`: Some(51), added: 546, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::PastBlocksWeight` (r:1 w:0) + /// Proof: `ProofsDealer::PastBlocksWeight` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTickerPaused` (r:0 w:1) + /// Proof: `ProofsDealer::ChallengesTickerPaused` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `MaxEncodedLen`) + fn check_spamming_condition() -> Weight { + // Proof Size summary in bytes: + // Measured: `248` + // Estimated: `3501` + // Minimum execution time: 13_925_000 picoseconds. + Weight::from_parts(14_476_000, 3501) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::LastDeletedTick` (r:1 w:0) + /// Proof: `ProofsDealer::LastDeletedTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn trim_valid_proof_submitters_last_ticks_constant_execution() -> Weight { + // Proof Size summary in bytes: + // Measured: `41` + // Estimated: `1489` + // Minimum execution time: 4_422_000 picoseconds. + Weight::from_parts(4_638_000, 1489) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: `ProofsDealer::LastDeletedTick` (r:0 w:1) + /// Proof: `ProofsDealer::LastDeletedTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ValidProofSubmittersLastTicks` (r:0 w:1) + /// Proof: `ProofsDealer::ValidProofSubmittersLastTicks` (`max_values`: None, `max_size`: Some(7830), added: 10305, mode: `MaxEncodedLen`) + fn trim_valid_proof_submitters_last_ticks_loop() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_453_000 picoseconds. + Weight::from_parts(2_608_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::PastBlocksWeight` (r:0 w:2) + /// Proof: `ProofsDealer::PastBlocksWeight` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + fn on_finalize() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 4_835_000 picoseconds. + Weight::from_parts(5_018_000, 0) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:0) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn force_initialise_challenge_cycle() -> Weight { + // Proof Size summary in bytes: + // Measured: `552` + // Estimated: `4624` + // Minimum execution time: 44_075_000 picoseconds. + Weight::from_parts(45_401_000, 4624) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `ProofsDealer::ChallengesTickerPaused` (r:0 w:1) + /// Proof: `ProofsDealer::ChallengesTickerPaused` (`max_values`: Some(1), `max_size`: Some(0), added: 495, mode: `MaxEncodedLen`) + fn set_paused() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_190_000 picoseconds. + Weight::from_parts(7_572_000, 0) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} diff --git a/operator/runtime/testnet/src/weights/pallet_session.rs b/operator/runtime/testnet/src/weights/pallet_session.rs new file mode 100644 index 00000000..154c1a57 --- /dev/null +++ b/operator/runtime/testnet/src/weights/pallet_session.rs @@ -0,0 +1,84 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_session` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-testnet-runtime/datahaven_testnet_runtime.compact.compressed.wasm +// --pallet +// pallet_session +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/testnet/src/weights/pallet_session.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_session`. +pub struct WeightInfo(PhantomData); +impl pallet_session::WeightInfo for WeightInfo { + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:4 w:4) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `350` + // Estimated: `11240` + // Minimum execution time: 37_208_000 picoseconds. + Weight::from_parts(38_300_000, 11240) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Session::NextKeys` (r:1 w:1) + /// Proof: `Session::NextKeys` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Session::KeyOwner` (r:0 w:4) + /// Proof: `Session::KeyOwner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn purge_keys() -> Weight { + // Proof Size summary in bytes: + // Measured: `328` + // Estimated: `3793` + // Minimum execution time: 21_720_000 picoseconds. + Weight::from_parts(22_535_000, 3793) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } +} diff --git a/operator/runtime/testnet/src/weights/pallet_storage_providers.rs b/operator/runtime/testnet/src/weights/pallet_storage_providers.rs new file mode 100644 index 00000000..663eb999 --- /dev/null +++ b/operator/runtime/testnet/src/weights/pallet_storage_providers.rs @@ -0,0 +1,630 @@ +// Copyright 2025 DataHaven +// This file is part of DataHaven. + +// DataHaven 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. + +// DataHaven 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 DataHaven. If not, see . + + +//! Autogenerated weights for `pallet_storage_providers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 51.0.0 +//! DATE: 2026-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// target/production/wbuild/datahaven-testnet-runtime/datahaven_testnet_runtime.compact.compressed.wasm +// --pallet +// pallet_storage_providers +// --extrinsic +// +// --header +// ../file_header.txt +// --template +// benchmarking/frame-weight-template.hbs +// --output +// runtime/testnet/src/weights/pallet_storage_providers.rs +// --steps +// 50 +// --repeat +// 20 + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_storage_providers`. +pub struct WeightInfo(PhantomData); +impl pallet_storage_providers::weights::WeightInfo for WeightInfo { + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn request_msp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 89_826_000 picoseconds. + Weight::from_parts(90_994_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + fn request_bsp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 89_741_000 picoseconds. + Weight::from_parts(91_222_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestOneEpochAgoRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestOneEpochAgoRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:0 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn confirm_sign_up_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `474` + // Estimated: `5628` + // Minimum execution time: 38_182_000 picoseconds. + Weight::from_parts(39_713_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Randomness::LatestOneEpochAgoRandomness` (r:1 w:0) + /// Proof: `Randomness::LatestOneEpochAgoRandomness` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:0 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn confirm_sign_up_msp() -> Weight { + // Proof Size summary in bytes: + // Measured: `487` + // Estimated: `5628` + // Minimum execution time: 54_783_000 picoseconds. + Weight::from_parts(56_744_000, 5628) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn cancel_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `507` + // Estimated: `5628` + // Minimum execution time: 65_446_000 picoseconds. + Weight::from_parts(66_906_000, 5628) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:102 w:101) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 100]`. + fn msp_sign_off(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `775 + n * (83 ±0)` + // Estimated: `8186 + n * (3598 ±0)` + // Minimum execution time: 93_251_000 picoseconds. + Weight::from_parts(91_955_675, 8186) + // Standard Error: 9_290 + .saturating_add(Weight::from_parts(6_491_321, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 3598).saturating_mul(n.into())) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:0) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + fn bsp_sign_off() -> Weight { + // Proof Size summary in bytes: + // Measured: `720` + // Estimated: `4624` + // Minimum execution time: 93_040_000 picoseconds. + Weight::from_parts(95_240_000, 4624) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn change_capacity_bsp_less_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `679` + // Estimated: `4624` + // Minimum execution time: 83_405_000 picoseconds. + Weight::from_parts(85_132_000, 4624) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn change_capacity_bsp_more_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `679` + // Estimated: `4624` + // Minimum execution time: 105_733_000 picoseconds. + Weight::from_parts(106_832_000, 4624) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn change_capacity_msp_less_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `649` + // Estimated: `4608` + // Minimum execution time: 79_140_000 picoseconds. + Weight::from_parts(80_429_000, 4608) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + fn change_capacity_msp_more_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `649` + // Estimated: `4608` + // Minimum execution time: 98_935_000 picoseconds. + Weight::from_parts(100_250_000, 4608) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + fn add_value_prop() -> Weight { + // Proof Size summary in bytes: + // Measured: `591` + // Estimated: `4608` + // Minimum execution time: 44_674_000 picoseconds. + Weight::from_parts(46_159_000, 4608) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + fn make_value_prop_unavailable() -> Weight { + // Proof Size summary in bytes: + // Measured: `631` + // Estimated: `4608` + // Minimum execution time: 32_741_000 picoseconds. + Weight::from_parts(34_206_000, 4608) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn add_multiaddress() -> Weight { + // Proof Size summary in bytes: + // Measured: `508` + // Estimated: `4624` + // Minimum execution time: 34_779_000 picoseconds. + Weight::from_parts(35_785_000, 4624) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn remove_multiaddress() -> Weight { + // Proof Size summary in bytes: + // Measured: `1316` + // Estimated: `4624` + // Minimum execution time: 32_789_000 picoseconds. + Weight::from_parts(33_844_000, 4624) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:1 w:1) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:0 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::PrivilegedProviders` (r:0 w:1) + /// Proof: `PaymentStreams::PrivilegedProviders` (`max_values`: None, `max_size`: Some(48), added: 2523, mode: `MaxEncodedLen`) + fn force_msp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 126_228_000 picoseconds. + Weight::from_parts(130_217_000, 5628) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::SignUpRequests` (r:1 w:1) + /// Proof: `Providers::SignUpRequests` (`max_values`: None, `max_size`: Some(2163), added: 4638, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:0 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + fn force_bsp_sign_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `270` + // Estimated: `5628` + // Minimum execution time: 106_118_000 picoseconds. + Weight::from_parts(107_693_000, 5628) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:1 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:0) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + fn slash_without_awaiting_top_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `871` + // Estimated: `6172` + // Minimum execution time: 162_133_000 picoseconds. + Weight::from_parts(164_580_000, 6172) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::SlashableProviders` (r:1 w:1) + /// Proof: `ProofsDealer::SlashableProviders` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `MaxEncodedLen`) + /// Storage: `Parameters::Parameters` (r:2 w:0) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(381), added: 2856, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ChallengesTicker` (r:1 w:0) + /// Proof: `ProofsDealer::ChallengesTicker` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::NextAvailableProviderTopUpExpirationShTick` (r:1 w:1) + /// Proof: `Providers::NextAvailableProviderTopUpExpirationShTick` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::ProviderTopUpExpirations` (r:1 w:1) + /// Proof: `Providers::ProviderTopUpExpirations` (`max_values`: None, `max_size`: Some(3322), added: 5797, mode: `MaxEncodedLen`) + fn slash_with_awaiting_top_up() -> Weight { + // Proof Size summary in bytes: + // Measured: `871` + // Estimated: `6787` + // Minimum execution time: 128_623_000 picoseconds. + Weight::from_parts(130_891_000, 6787) + .saturating_add(T::DbWeight::get().reads(13_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:1 w:0) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::ProviderTopUpExpirations` (r:0 w:1) + /// Proof: `Providers::ProviderTopUpExpirations` (`max_values`: None, `max_size`: Some(3322), added: 5797, mode: `MaxEncodedLen`) + fn top_up_deposit() -> Weight { + // Proof Size summary in bytes: + // Measured: `758` + // Estimated: `4624` + // Minimum execution time: 113_271_000 picoseconds. + Weight::from_parts(115_045_000, 4624) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: `Providers::InsolventProviders` (r:2 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:1) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:1) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::BspCount` (r:1 w:1) + /// Proof: `Providers::BspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::TotalBspsCapacity` (r:1 w:1) + /// Proof: `Providers::TotalBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::UsedBspsCapacity` (r:1 w:1) + /// Proof: `Providers::UsedBspsCapacity` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `Providers::GlobalBspsReputationWeight` (r:1 w:1) + /// Proof: `Providers::GlobalBspsReputationWeight` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn delete_provider_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `853` + // Estimated: `6038` + // Minimum execution time: 81_453_000 picoseconds. + Weight::from_parts(84_499_000, 6038) + .saturating_add(T::DbWeight::get().reads(12_u64)) + .saturating_add(T::DbWeight::get().writes(9_u64)) + } + /// Storage: `Providers::InsolventProviders` (r:1 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::FixedRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::FixedRatePaymentStreams` (`max_values`: None, `max_size`: Some(125), added: 2600, mode: `MaxEncodedLen`) + /// Storage: `PaymentStreams::DynamicRatePaymentStreams` (r:1 w:0) + /// Proof: `PaymentStreams::DynamicRatePaymentStreams` (`max_values`: None, `max_size`: Some(129), added: 2604, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:1) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToValuePropositions` (r:22 w:21) + /// Proof: `Providers::MainStorageProviderIdsToValuePropositions` (`max_values`: None, `max_size`: Some(1123), added: 3598, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviderIdsToBuckets` (r:21 w:20) + /// Proof: `Providers::MainStorageProviderIdsToBuckets` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) + /// Storage: `Providers::MspCount` (r:1 w:1) + /// Proof: `Providers::MspCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToMainStorageProviderId` (r:0 w:1) + /// Proof: `Providers::AccountIdToMainStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 20]`. + /// The range of component `m` is `[0, 20]`. + fn delete_provider_msp(n: u32, m: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1845 + m * (54 ±0) + n * (83 ±0)` + // Estimated: `8186 + m * (2571 ±0) + n * (3598 ±0)` + // Minimum execution time: 186_516_000 picoseconds. + Weight::from_parts(80_100_317, 8186) + // Standard Error: 31_923 + .saturating_add(Weight::from_parts(6_927_784, 0).saturating_mul(n.into())) + // Standard Error: 31_923 + .saturating_add(Weight::from_parts(5_691_747, 0).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(m.into()))) + .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(m.into()))) + .saturating_add(Weight::from_parts(0, 2571).saturating_mul(m.into())) + .saturating_add(Weight::from_parts(0, 3598).saturating_mul(n.into())) + } + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:0) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + fn stop_all_cycles() -> Weight { + // Proof Size summary in bytes: + // Measured: `549` + // Estimated: `4624` + // Minimum execution time: 27_371_000 picoseconds. + Weight::from_parts(28_106_000, 4624) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::AccountIdToBackupStorageProviderId` (r:1 w:0) + /// Proof: `Providers::AccountIdToBackupStorageProviderId` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::ProviderToProofSubmissionRecord` (r:1 w:1) + /// Proof: `ProofsDealer::ProviderToProofSubmissionRecord` (`max_values`: None, `max_size`: Some(56), added: 2531, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:0 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + /// Storage: `ProofsDealer::TickToProvidersDeadlines` (r:0 w:1) + /// Proof: `ProofsDealer::TickToProvidersDeadlines` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + fn process_expired_provider_top_up_bsp() -> Weight { + // Proof Size summary in bytes: + // Measured: `1038` + // Estimated: `6172` + // Minimum execution time: 103_589_000 picoseconds. + Weight::from_parts(106_013_000, 6172) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: `Providers::AwaitingTopUpFromProviders` (r:1 w:1) + /// Proof: `Providers::AwaitingTopUpFromProviders` (`max_values`: None, `max_size`: Some(57), added: 2532, mode: `MaxEncodedLen`) + /// Storage: `Providers::BackupStorageProviders` (r:1 w:0) + /// Proof: `Providers::BackupStorageProviders` (`max_values`: None, `max_size`: Some(1159), added: 3634, mode: `MaxEncodedLen`) + /// Storage: `Providers::MainStorageProviders` (r:1 w:0) + /// Proof: `Providers::MainStorageProviders` (`max_values`: None, `max_size`: Some(1143), added: 3618, mode: `MaxEncodedLen`) + /// Storage: `Balances::Holds` (r:1 w:1) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(289), added: 2764, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:2 w:2) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) + /// Storage: `Providers::InsolventProviders` (r:0 w:1) + /// Proof: `Providers::InsolventProviders` (`max_values`: None, `max_size`: Some(49), added: 2524, mode: `MaxEncodedLen`) + fn process_expired_provider_top_up_msp() -> Weight { + // Proof Size summary in bytes: + // Measured: `775` + // Estimated: `6172` + // Minimum execution time: 83_393_000 picoseconds. + Weight::from_parts(84_682_000, 6172) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } +} diff --git a/specs/validator-set-selection/validator-set-selection.md b/specs/validator-set-selection/validator-set-selection.md new file mode 100644 index 00000000..b13f4680 --- /dev/null +++ b/specs/validator-set-selection/validator-set-selection.md @@ -0,0 +1,247 @@ +# Validator Set Selection Specification +## Top-32 by Weighted Stake (Continuation of PR #433) + +- Status: Draft +- Owners: DataHaven Team +- Last Updated: February 12, 2026 +- Depends on: PR #433 (`feat: automated validator set submission with era targeting`) + +## 1. Summary + +PR #433 introduced era-targeted validator-set submission with a dedicated submitter role and runtime era validation. This spec is a continuation of that work. + +This document adds deterministic weighted-stake selection so the outbound validator set is ranked before it is bridged: + +1. Ethereum computes weighted stake per operator. +2. Ethereum deterministically sorts operators and selects top candidates. +3. DataHaven enforces a final total active authority cap of 32 after combining whitelisted and external validators. + +The era-targeting model from PR #433 remains unchanged. + +## 2. Baseline From PR #433 + +This spec assumes the following behavior already exists: + +1. `DataHavenServiceManager.sendNewValidatorSetForEra(uint64 targetEra, ...)` is used for submission. +2. Submission is restricted to `validatorSetSubmitter` (`onlyValidatorSetSubmitter`). +3. `external_index` in the Snowbridge payload is the `targetEra`. +4. DataHaven runtime enforces era validity (`targetEra` old/too-new/duplicate checks). + +## 3. Goals + +1. Select external validators by weighted stake instead of raw member ordering. +2. Keep selection deterministic (`same chain state -> same selected set`). +3. Preserve PR #433 era-targeting invariants and submitter authorization flow. +4. Enforce total active authority cap = 32 (`whitelisted + external`). +5. Keep payload shape stable unless there is a hard requirement to version it. + +## 4. Non-Goals + +1. Replacing PR #433 submitter-role model. +2. Changing PR #433 era-target validation semantics. +3. Redesigning Snowbridge transport internals. +4. Changing reward formulas in this spec. + +## 5. Current Behavior (Post-PR #433) + +### 5.1 Ethereum + +`buildNewValidatorSetMessageForEra(targetEra)` gathers all operator-set members with a mapped solochain address and forwards them in that order. There is no stake-based ranking. + +### 5.2 Payload + +Current payload carries: + +1. `validators` +2. `external_index` (interpreted as `targetEra`) + +### 5.3 DataHaven Runtime + +`set_external_validators_inner()` stores incoming validators and `ExternalIndex`, then era application and validator composition logic consume them. + +### 5.4 Limitation + +Without stake-aware ordering, high-stake operators may be displaced by lower-stake operators when list size pressure or downstream caps apply. + +## 6. Design Decisions + +### D1. Do ranking on Ethereum + +EigenLayer membership/allocation context is available on Ethereum, so weighted ranking is computed there. + +### D2. Keep PR #433 era semantics unchanged + +`external_index` must continue to encode `targetEra`. This spec does not repurpose it (no nonce/block-number substitution). + +### D3. Deterministic tie-break + +For equal weighted stake, lower Ethereum operator address wins. + +### D4. Cap applies to total active authorities + +Final active validator set must satisfy: + +`final_active = take_32(dedupe(whitelisted ++ external_sorted_limited))` + +### D5. Strategy multipliers are explicit and default to zero if unset + +Multipliers are owner-managed in `strategiesAndMultipliers`. If an entry is unset for a strategy, its effective multiplier is `0` (no weighted contribution). + +### D6. Keep strategy list and multipliers in sync + +Multiplier lifecycle is tied to strategy lifecycle: + +1. Add strategy -> add multiplier in the same call via `IRewardsCoordinatorTypes.StrategyAndMultiplier` struct. +2. Remove strategy -> delete multiplier in the same call. + +## 7. Weighted Stake Model + +For each operator `o`: + +`weightedStake(o) = sum_i( allocatedStake(o, strategy_i) * multiplier(strategy_i) )` + +Where: + +1. `allocatedStake` comes from EigenLayer allocation data. +2. `multiplier` is a per-strategy weight (no normalization divisor is applied during ranking). + +### 7.1 Strategy Weight Semantics + +1. Every supported strategy should have an explicit multiplier entry for operational clarity. +2. Missing multiplier entry is treated as `0` multiplier. +3. Multiplier values are managed explicitly by owner/governance. + +### 7.2 Unit Assumption + +Stake inputs must be unit-consistent across strategies. If they are not, normalize before summing. + +## 8. Ethereum Contract Changes (On Top of PR #433) + +File: `contracts/src/DataHavenServiceManager.sol` + +### 8.1 New State + +```solidity +uint32 public constant MAX_ACTIVE_VALIDATORS = 32; +mapping(IStrategy => uint96) public strategiesAndMultipliers; +``` + +### 8.2 New/Updated Admin APIs + +```solidity +function setStrategiesAndMultipliers(IRewardsCoordinatorTypes.StrategyAndMultiplier[] calldata strategyMultipliers) external onlyOwner; +function addStrategiesToValidatorsSupportedStrategies(IRewardsCoordinatorTypes.StrategyAndMultiplier[] calldata strategyMultipliers) external onlyOwner; +function removeStrategiesFromValidatorsSupportedStrategies(IStrategy[] calldata strategies) external onlyOwner; +function getStrategiesAndMultipliers() external view returns (IRewardsCoordinatorTypes.StrategyAndMultiplier[] memory); +``` + +Using EigenLayer's `StrategyAndMultiplier` struct pairs each strategy with its multiplier, eliminating the possibility of length mismatches between parallel arrays. Duplicate strategies in `addStrategies` are rejected by EigenLayer's `StrategyAlreadyInOperatorSet` check; duplicates in `setStrategiesAndMultipliers` are harmless (last-write-wins on the mapping). + +### 8.3 Updated Selection Flow + +`buildNewValidatorSetMessageForEra(uint64 targetEra)` should: + +1. Read validator operator set members. +2. Compute weighted stake per operator. +3. Filter out operators with no solochain mapping. +4. Resolve multiplier from `strategiesAndMultipliers` for each strategy used. +5. If any strategy is missing a multiplier entry, treat it as `0` multiplier. +6. Filter out operators with zero weighted stake. +7. Select at most `MAX_ACTIVE_VALIDATORS` (32) candidates by weighted stake desc + address asc tie-break (if fewer than 32 eligible candidates exist, include all). +8. Encode using existing payload shape with `externalIndex = targetEra`. + +For any EigenLayer call that consumes `StrategyAndMultiplier[]`, materialize the list in ascending strategy-address order. + +`sendNewValidatorSetForEra(...)` and `onlyValidatorSetSubmitter` remain unchanged from PR #433. + +## 9. Bridge Message Format + +No payload version bump in this spec. + +Continue using existing `ReceiveValidators` message shape: + +```text +[EL_MESSAGE_ID] +[MessageVersion] +[ReceiveValidators] +[validator_count] +[validators (N * 20B)] +[external_index (u64 targetEra)] +``` + +If stake vectors are required in the future, that should be a separate versioned command proposal. + +## 10. DataHaven Runtime Changes + +File: `operator/pallets/external-validators/src/lib.rs` + +### 10.1 Keep PR #433 era validation + +Retain existing target-era gates and error semantics (`TargetEraTooOld`, `TargetEraTooNew`, `DuplicateOrStaleTargetEra`). + +### 10.2 Enforce final total cap = 32 + +At validator composition time: + +1. `w = whitelisted.len()` +2. `external_budget = 32.saturating_sub(w)` +3. Use at most `external_budget` external validators from the ranked list. +4. Build final set as `take_32(dedupe(whitelisted ++ external_limited))`. + +### 10.3 Runtime constants + +`MaxExternalValidators` can remain a defensive bound, but final active enforcement must guarantee max 32 authorities. + +## 11. Rollout Plan + +1. Merge/deploy PR #433 baseline first (submitter role + era-target checks). +2. Deploy ServiceManager upgrade with weighted ranking logic. +3. Backfill/confirm `strategiesAndMultipliers` for all currently supported strategies. +4. Deploy runtime changes for final total-cap enforcement. +5. Re-run submitter daemon unchanged (it still submits `targetEra = ActiveEra + 1`). +6. Monitor across multiple era cycles before production rollout. + +## 12. Testing Plan + +### 12.1 Solidity + +1. Weighted stake computation across multiple strategies. +2. Deterministic tie-break behavior. +3. Top-32 selection when candidate count exceeds 32. +4. Behavior when candidate count is below 32. +5. Zero-stake filtering. +6. Missing multiplier entries are treated as zero contribution. +7. `addStrategies...` sets multipliers atomically via `StrategyAndMultiplier` struct. +8. `removeStrategies...` removes multiplier entries for removed strategies. +9. `getStrategiesAndMultipliers()` returns a list matching EigenLayer's operator set strategies. +11. Integration with `buildNewValidatorSetMessageForEra(targetEra)` and correct target era encoding. + +### 12.2 Runtime + +1. Existing PR #433 era-validation tests continue to pass unchanged. +2. Final active authority cap remains <= 32 with mixed whitelisted/external sets. +3. Composition logic preserves whitelisted priority while enforcing cap. + +### 12.3 Integration / E2E + +1. End-to-end submission through `sendNewValidatorSetForEra` with ranked validator output. +2. Delayed relay still fails with PR #433 semantics (no regressions). +3. Ranked selection outcome is deterministic across repeated runs at fixed state. + +## 13. Security Considerations + +1. Owner-managed strategy weights are governance-sensitive and should remain multisig/governance controlled. +2. Deterministic ordering prevents non-deterministic set drift. +3. Preserve PR #433 stale/duplicate/too-early rejection invariants. +4. Apply overflow checks in weighted arithmetic and any integer downcasts. + +## 14. File Change Summary + +1. `contracts/src/DataHavenServiceManager.sol` + - weighted stake computation and deterministic top selection in `buildNewValidatorSetMessageForEra`. +2. `contracts/src/interfaces/IDataHavenServiceManager.sol` + - `strategiesAndMultipliers` naming and add/remove strategy API signature updates with multipliers. +3. `operator/pallets/external-validators/src/lib.rs` + - final authority cap enforcement at composition time (while keeping PR #433 era validation behavior). +4. `contracts/test/*`, `operator/pallets/external-validators/src/tests.rs`, `test/e2e/suites/validator-set-update.test.ts` + - unit/runtime/e2e coverage for weighted selection + strategy/multiplier sync + cap behavior + non-regression on era-targeted flow. diff --git a/specs/validator-set-submission/validator-set-submission.md b/specs/validator-set-submission/validator-set-submission.md new file mode 100644 index 00000000..bfcf47b6 --- /dev/null +++ b/specs/validator-set-submission/validator-set-submission.md @@ -0,0 +1,268 @@ +# Validator Set Submission +**Status:** Accepted +**Owner:** DataHaven Protocol / AVS Integration +**Last Updated:** 2026-02-11 +**Scope:** Ethereum -> Snowbridge -> DataHaven validator set synchronization + +## Background +This specification defines an automation-first validator-set synchronization flow. +In this document: +- the validator-set submitter runs once per era window, and +- each message is valid only for the immediate next era. +The primary objective is to run an off-chain validator-set-submitter that automatically calls validator-set submission without manual intervention. +The design is: +1. Validator-set messages are permissioned on Ethereum by a dedicated submitter role. +2. The payload field `external_index` is used as `targetEra` (the era the message is intended for). +3. DataHaven accepts a message only if it targets the next era at receive time. +4. Delayed messages for past eras are rejected and never applied to later eras. +This enforces the invariant: **at most one canonical validator-set apply per target era, and no late-era spillover**. + +### Current mechanism (as-is) +- Manual and one-shot submission flow is done via `test/scripts/update-validator-set.ts`. +- `sendNewValidatorSet(uint128 executionFee, uint128 relayerFee)` in `contracts/src/DataHavenServiceManager.sol` is owner-only. +- Message building currently does not carry explicit era intent. +- DataHaven inbound processing applies decoded `external_index` without era-target validation. +- Operational flow relies on fixed fee constants and has no automated submission pipeline. + +## Problems addressed by this spec +- Manual operation for validator-set submission. +- Late relay can cause old messages to arrive after their intended era. +- Ambiguity between "message order" and "era intent". +- Owner-key usage for routine automated submissions. + +## Goals +1. Run an off-chain component that automatically submits validator-set updates in the required era window. +2. Ensure each message is explicitly bound to a specific target era. +3. Accept a message only when it targets the immediate next era. +4. Reject delayed (past-era), duplicate, and too-far-ahead messages deterministically. +5. Accept that a failed submission for a given era is permanently missed (single submission window per era). +6. Avoid skipping era advancement even when validator addresses are unchanged. + +### Non-goals +- Redesigning Snowbridge protocol internals. +- Replacing the existing owner/governance model outside submitter assignment. +- Building a multi-node HA control plane (single submitter process is acceptable initially). + +## Terminology +- `ActiveEra`: era currently active on DataHaven. +- `NextEra`: `ActiveEra + 1`. +- `targetEra`: era this validator-set message is intended for. +- `external_index`: payload field; in this design, its value is `targetEra`. +- `ExternalIndex`: latest bridge-received `targetEra` accepted on DataHaven. +- `PendingExternalIndex`: staged external index applied when the next era starts. +- `CurrentExternalIndex`: external index currently applied to the active era. +- `Canonical apply`: the accepted validator-set apply for a specific `targetEra`. + +## Proposed design + +### High-level overview +The solution centers on a long-running off-chain validator-set-submitter under `test/tools/` that automatically submits validator-set updates. +Contract and runtime changes make the submitter service safe and deterministic: +- only the submitter role can send validator-set messages, +- payloads include explicit era intent (`targetEra`), and +- DataHaven accepts only messages targeting `NextEra`. +The submitter subscribes to finalized session changes via PAPI's `watchValue("finalized")` on `Session.CurrentIndex`. On each session change it evaluates whether submission is needed, and acts during the last session of the active era. Each era gets a single submission attempt — if it fails, the era is missed and the submitter moves on. + +``` +┌───────────────────────────────┐ submit (for era) ┌───────────────────────────────┐ +│ Validator-Set-Submitter │ ──────────────────────────► │ ServiceManager (Ethereum) │ +│ - watches session changes │ │ - submitter-gated API │ +│ - computes targetEra │ │ - builds payload with target │ +│ - single attempt per era │ └───────────────┬───────────────┘ +└───────────────────────────────┘ │ + │ Snowbridge message + ▼ +┌────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ DataHaven inbound (`operator/primitives/bridge`) + external validators pallet │ +│ - authorized origin check │ +│ - era gate: targetEra == ActiveEra + 1 │ +│ - duplicate/stale gate: targetEra > ExternalIndex │ +│ - delayed messages for past eras are rejected │ +└────────────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +### A) Ethereum contract changes +**Target contract** +- `contracts/src/DataHavenServiceManager.sol` + +**Permissioned submitter role** +- Add state: + - `address public validatorSetSubmitter` +- Add admin API: + - `setValidatorSetSubmitter(address newSubmitter) external onlyOwner` + - `newSubmitter` MUST be non-zero + - emit `ValidatorSetSubmitterUpdated(oldSubmitter, newSubmitter)` +- Add modifier: + - `onlyValidatorSetSubmitter` (revert unless `msg.sender == validatorSetSubmitter`) + +**Era-targeted submission** +- Add submission API: + - `sendNewValidatorSetForEra(uint64 targetEra, uint128 executionFee, uint128 relayerFee) external payable onlyValidatorSetSubmitter` + - builds validator payload with `targetEra` + - calls gateway `v2_sendMessage` + - emits `ValidatorSetMessageSubmitted` +- Add builder API: + - `buildNewValidatorSetMessageForEra(uint64 targetEra) public view returns (bytes memory)` + - encodes `targetEra` as `external_index` + +**Legacy submission path** +- Legacy `sendNewValidatorSet(uint128,uint128)` must be removed from the production contract. + +**Contract-side trust scope (this release)** +- No additional `lastSubmittedTargetEra` contract guard is required in this release. +- Rationale: submission is permissioned and runtime is the source of truth for era correctness (`targetEra == ActiveEra + 1`). + +**Events** +- `event ValidatorSetSubmitterUpdated(address indexed oldSubmitter, address indexed newSubmitter);` +- `event ValidatorSetMessageSubmitted(uint64 indexed targetEra, bytes32 payloadHash, address indexed submitter);` + +### B) Runtime changes (DataHaven) +**Target processor** +- `operator/primitives/bridge/src/lib.rs` in `EigenLayerMessageProcessor::process_message` + +**Era-target validation rule** +Before `set_external_validators_inner`, validate `targetEra`: +1. Must satisfy `targetEra == ActiveEra + 1` +2. Must satisfy `targetEra > ExternalIndex` (dedupe/stale guard) +Reject cases: +- `targetEra <= ActiveEra`: delayed/past-era message. +- `targetEra > ActiveEra + 1`: too-far-ahead message. +- `targetEra <= ExternalIndex`: stale/duplicate message. +This ensures a delayed message cannot be applied to a later era. + +**Error semantics** +Return deterministic dispatch errors, for example: +- `TargetEraTooOld` +- `TargetEraTooNew` +- `DuplicateOrStaleTargetEra` + +**Authorization** +- Keep existing authorized-origin checks unchanged. + +### C) Validator-set-submitter service (`test/tools/`) +**Location and runtime model** +- New component at `test/tools/validator-set-submitter/` +- Long-running daemon +- TypeScript + Bun + +**Authoritative inputs** +- DataHaven: + - `ActiveEra` + - `ExternalIndex` + - `CurrentExternalIndex` + - `SessionsPerEra` and era-window session boundaries +- Ethereum: + - current validator set view from ServiceManager message-builder inputs + +**Target era computation** +- `targetEra = ActiveEra + 1` + +**Submission model** +- Submitter subscribes to finalized `Session.CurrentIndex` via PAPI `watchValue("finalized")`. +- On each session change, evaluates preconditions: `ActiveEra` set, `targetEra` not already processed, `ExternalIndex < targetEra`, and current session is the last session of the era. +- One submission attempt per era window. If the attempt fails (revert, missing event, or error), the era is marked as processed and permanently missed. +- Rationale: `validate_target_era` on the Substrate side rejects `targetEra <= activeEraIndex`, so once `ActiveEra` advances past the target, retries are impossible. +- Overlapping session emissions are dropped via RxJS `exhaustMap`. + +**Delay/gap behavior (required)** +- If message for era `N` is delayed and arrives after `ActiveEra >= N`, it is rejected. +- If message for era `N` never relays, the system can still proceed by submitting for era `N+1` when `ActiveEra = N`. +- Out-of-order future messages are rejected until they become the next era target. + +**Success criteria** +- Transaction receipt status is `success`. +- `OutboundMessageAccepted` event emitted in receipt logs. + +**State model** +- Submitter is recoverable from chain state (reads `ActiveEra`, `ExternalIndex`, and session boundaries on each tick). +- In-memory state is limited to `submittedEra` (the last processed target era), held in a closure. + +## API / interface changes + +### Ethereum interface +- Add era-targeted submit function. +- Add submitter admin function + getter. +- Add era-targeted builder function. + +### DataHaven runtime behavior +- Add next-era-only acceptance in inbound bridge path. +- Add explicit delayed/too-early/duplicate rejection paths. + +### Tooling +- New daemon CLI entrypoint: + - `bun test/tools/validator-set-submitter/main.ts run` + - optional `--dry-run` + +## Security considerations +- Submitter key compromise risk is reduced by dedicated role separation (vs broad owner use). +- Era-target checks prevent delayed-message replay into later eras. +- Authorized-origin restriction remains required and unchanged. +- Single-attempt model eliminates fee burn loops; a failed era is missed rather than retried. + +## Observability and operations +Required metrics/log dimensions: +- `targetEra` +- current `ActiveEra` and `ExternalIndex` +- current session index +- outbound tx hash +- fee pair used +- submission outcome (success / revert / missing event / error) +Alert conditions: +- missed submission window (failed attempt logged as "era will be missed") +- repeated era misses across consecutive eras +- subscription errors on `Session.CurrentIndex` + +## Testing + +### Solidity tests +- submitter-only enforcement +- submitter rotation by owner +- payload encodes caller `targetEra` +- event fields emitted correctly +- zero-address submitter rejected +- legacy `sendNewValidatorSet` path is removed (no callable legacy submit path) + +### Runtime tests +- accepts only `targetEra == ActiveEra + 1` +- rejects `targetEra <= ActiveEra` (late) +- rejects `targetEra > ActiveEra + 1` (too early) +- rejects `targetEra <= ExternalIndex` (duplicate/stale) +- origin authorization behavior unchanged + +### Integration tests +- one canonical apply per target era +- delayed message for old era is rejected after era advances +- missing relay for era `N` does not block acceptance for era `N+1` when it becomes next +- boundary race: arrival at era transition behaves correctly (`N` stale, `N+1` accepted) + +## Rollout +1. Implement and test contract + runtime changes. +2. Deploy to stagenet. +3. Run submitter service in dry-run mode and validate era-target decisions. +4. Enable active mode. +5. Monitor across multiple era cycles. +6. Promote to mainnet after stability criteria are met. + +## Dependencies +- Existing manual script `test/scripts/update-validator-set.ts` may remain for emergency/manual use, but must be marked non-canonical. +- Legacy unscoped submit path `sendNewValidatorSet` must be removed in production. + +## Possible improvements (future) +- Keep this release simple: `external_index` carries `targetEra`, and runtime enforces next-era-only acceptance. +- Add a generalized failure-handling strategy for the submitter, including retry behavior for transient issues while preserving safety and idempotency. +- Add generalized resiliency for event watching and connectivity, including recovery after disconnects and missed updates. +- Add production monitoring and operations dashboards (for example Prometheus/Grafana) covering service health, submission outcomes, retries, missed eras, and end-to-end latency. +- Add alerting/SLO definitions for validator-set submission reliability and response runbooks for incidents. +- Alternative direction: remove era dependency from payload and use an Ethereum-stamped freshness model: + - `ServiceManager` assigns message metadata on-chain (e.g., `issuedAt` timestamp and monotonic message nonce/ID). + - DataHaven accepts only fresh messages within a configured max relay delay and rejects expired ones. + - This reduces trust in submitter-provided era values while preserving deterministic stale/duplicate rejection. + +## Acceptance criteria +This spec is accepted when: +- an off-chain validator-set-submitter runs unattended and automatically submits validator-set updates +- dedicated submitter role exists and is enforced +- era-targeted submission API is live +- runtime applies messages only when they target the next era +- delayed messages for past eras are rejected and not applied to later eras +- end-to-end tests pass for delayed/missing/out-of-order scenarios diff --git a/test/.papi/descriptors/package.json b/test/.papi/descriptors/package.json index 8ece9265..d7be6139 100644 --- a/test/.papi/descriptors/package.json +++ b/test/.papi/descriptors/package.json @@ -1,5 +1,5 @@ { - "version": "0.1.0-autogenerated.14314240478086326730", + "version": "0.1.0-autogenerated.13357056092938763018", "name": "@polkadot-api/descriptors", "files": [ "dist" diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index 0fdd8917..5b2fcad3 100644 Binary files a/test/.papi/metadata/datahaven.scale and b/test/.papi/metadata/datahaven.scale differ diff --git a/test/cli/handlers/contracts/beefy-checkpoint.ts b/test/cli/handlers/contracts/beefy-checkpoint.ts new file mode 100644 index 00000000..6ad07261 --- /dev/null +++ b/test/cli/handlers/contracts/beefy-checkpoint.ts @@ -0,0 +1,305 @@ +import invariant from "tiny-invariant"; +import { logger, printDivider, printHeader } from "utils"; +import { createPapiConnectors } from "utils/papi"; +import { type Hex, keccak256 } from "viem"; +import { buildNetworkId } from "../../../configs/contracts/config"; +import { compressedPubKeyToEthereumAddress } from "../../../launcher/datahaven"; + +interface UpdateBeefyCheckpointOptions { + chain: string; + environment?: string; + rpcUrl: string; +} + +interface BeefyCheckpointData { + startBlock: number; + minNumRequiredSignatures: number; + initialValidatorSetId: number; + initialValidatorHashes: string[]; + nextValidatorSetId: number; + nextValidatorHashes: string[]; +} + +/** + * Converts an array of compressed public keys to authority hashes. + * + * @param authorityPublicKeys - Array of compressed public keys as hex strings + * @returns Array of authority hashes (keccak256 of Ethereum addresses) + */ +const computeAuthorityHashes = (authorityPublicKeys: string[]): string[] => { + const authorityHashes: string[] = []; + for (const compressedKey of authorityPublicKeys) { + const ethAddress = compressedPubKeyToEthereumAddress(compressedKey); + const authorityHash = keccak256(ethAddress as Hex); + authorityHashes.push(authorityHash); + logger.debug( + ` ${compressedKey.slice(0, 20)}... -> ${ethAddress} -> ${authorityHash.slice(0, 20)}...` + ); + } + return authorityHashes; +}; + +/** + * Calculates the minimum number of required signatures for BFT security. + * Uses the same formula as Snowbridge's BeefyClient contract to ensure + * strictly more than 2/3 of validators must sign. + * + * Formula: n - floor((n-1)/3) + * + * This ensures strictly > 2/3 majority. For example: + * - n=3: returns 3 (not 2, which would be exactly 2/3) + * - n=6: returns 5 (not 4, which would be exactly 2/3) + * - n=100: returns 67 (strictly > 66.67) + * + * @see https://github.com/datahaven-xyz/snowbridge/blob/main/contracts/src/BeefyClient.sol + * @param validatorCount - The number of validators + * @returns The minimum number of required signatures + */ +const calculateMinRequiredSignatures = (validatorCount: number): number => { + // For BFT security, we need strictly > 2/3 of validators to sign + // This matches Snowbridge's computeQuorum function + if (validatorCount <= 3) { + return validatorCount; + } + return validatorCount - Math.floor((validatorCount - 1) / 3); +}; + +/** + * Fetches BEEFY checkpoint data from a DataHaven chain including both current and next + * authority sets along with their validator set IDs, the latest finalized block, + * and calculates the minimum required signatures. + * + * All queries are performed at the same finalized block to ensure consistency. + * + * @param rpcUrl - WebSocket RPC endpoint of the DataHaven chain + * @returns BEEFY checkpoint data with validator set IDs, authority hashes, startBlock, and minNumRequiredSignatures + */ +const fetchBeefyCheckpointData = async (rpcUrl: string): Promise => { + logger.info(`📡 Connecting to DataHaven chain at ${rpcUrl}...`); + + const { client: papiClient, typedApi: dhApi } = createPapiConnectors(rpcUrl); + + try { + // First, get the finalized block hash to use for all subsequent queries + logger.info("🔍 Fetching latest finalized block..."); + const finalizedBlock = await papiClient.getFinalizedBlock(); + const startBlock = finalizedBlock.number; + const blockHash = finalizedBlock.hash; + logger.success(`Latest finalized block: ${startBlock} (${blockHash})`); + + // Fetch all BEEFY data in parallel at the same finalized block + logger.info("🔍 Fetching BEEFY data (ValidatorSetId, Authorities, NextAuthorities)..."); + const [validatorSetId, authoritiesRaw, nextAuthoritiesRaw] = await Promise.all([ + dhApi.query.Beefy.ValidatorSetId.getValue({ at: blockHash }), + dhApi.query.Beefy.Authorities.getValue({ at: blockHash }), + dhApi.query.Beefy.NextAuthorities.getValue({ at: blockHash }) + ]); + + // Validate results + invariant(validatorSetId !== undefined, "Failed to fetch BEEFY ValidatorSetId"); + logger.success(`Current ValidatorSetId: ${validatorSetId}`); + + invariant( + authoritiesRaw && authoritiesRaw.length > 0, + "No BEEFY Authorities found on the chain" + ); + const currentAuthorityKeys = authoritiesRaw.map((key) => key.asHex()); + logger.success(`Found ${currentAuthorityKeys.length} current BEEFY authorities`); + + invariant( + nextAuthoritiesRaw && nextAuthoritiesRaw.length > 0, + "No BEEFY NextAuthorities found on the chain" + ); + const nextAuthorityKeys = nextAuthoritiesRaw.map((key) => key.asHex()); + logger.success(`Found ${nextAuthorityKeys.length} next BEEFY authorities`); + + // Calculate minimum required signatures based on validator count + // Uses Snowbridge's formula: n - floor((n-1)/3) for strictly > 2/3 majority + const minNumRequiredSignatures = calculateMinRequiredSignatures(currentAuthorityKeys.length); + logger.info( + `📊 Minimum required signatures: ${minNumRequiredSignatures} (${currentAuthorityKeys.length} - floor((${currentAuthorityKeys.length}-1)/3))` + ); + + // Compute hashes for both sets + logger.info("🔐 Computing authority hashes for current set..."); + const initialValidatorHashes = computeAuthorityHashes(currentAuthorityKeys); + + logger.info("🔐 Computing authority hashes for next set..."); + const nextValidatorHashes = computeAuthorityHashes(nextAuthorityKeys); + + // Check if the sets are identical + const setsAreIdentical = + JSON.stringify(initialValidatorHashes) === JSON.stringify(nextValidatorHashes); + if (setsAreIdentical) { + logger.info("ℹ️ Current and next authority sets are identical"); + } else { + logger.info("ℹ️ Current and next authority sets differ"); + } + + return { + startBlock, + minNumRequiredSignatures, + initialValidatorSetId: Number(validatorSetId), + initialValidatorHashes, + nextValidatorSetId: Number(validatorSetId) + 1, + nextValidatorHashes + }; + } finally { + papiClient.destroy(); + } +}; + +/** + * Updates the config file with the fetched BEEFY checkpoint data. + * + * @param networkId - The network identifier (e.g., "hoodi", "stagenet-hoodi") + * @param checkpointData - BEEFY checkpoint data including validator set IDs, hashes, startBlock, and minNumRequiredSignatures + */ +const updateConfigFile = async ( + networkId: string, + checkpointData: BeefyCheckpointData +): Promise => { + const configFilePath = `../contracts/config/${networkId}.json`; + const configFile = Bun.file(configFilePath); + + if (!(await configFile.exists())) { + throw new Error(`Configuration file not found: ${configFilePath}`); + } + + const configContent = await configFile.text(); + const configJson = JSON.parse(configContent); + + if (!configJson.snowbridge) { + logger.warn(`"snowbridge" section not found in config, creating it.`); + configJson.snowbridge = {}; + } + + // Store the old values for comparison + const oldStartBlock = configJson.snowbridge.startBlock; + const oldMinSigs = configJson.snowbridge.minNumRequiredSignatures; + const oldInitialId = configJson.snowbridge.initialValidatorSetId; + const oldNextId = configJson.snowbridge.nextValidatorSetId; + const oldInitial = configJson.snowbridge.initialValidatorHashes || []; + const oldNext = configJson.snowbridge.nextValidatorHashes || []; + + // Update with new values + configJson.snowbridge.startBlock = checkpointData.startBlock; + configJson.snowbridge.minNumRequiredSignatures = checkpointData.minNumRequiredSignatures; + configJson.snowbridge.initialValidatorSetId = checkpointData.initialValidatorSetId; + configJson.snowbridge.initialValidatorHashes = checkpointData.initialValidatorHashes; + configJson.snowbridge.nextValidatorSetId = checkpointData.nextValidatorSetId; + configJson.snowbridge.nextValidatorHashes = checkpointData.nextValidatorHashes; + + await Bun.write(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`); + + logger.success(`Config file updated: ${configFilePath}`); + + // Show what changed + if (oldStartBlock !== checkpointData.startBlock) { + logger.info(` startBlock: ${oldStartBlock ?? "unset"} -> ${checkpointData.startBlock}`); + } + if (oldMinSigs !== checkpointData.minNumRequiredSignatures) { + logger.info( + ` minNumRequiredSignatures: ${oldMinSigs ?? "unset"} -> ${checkpointData.minNumRequiredSignatures}` + ); + } + if (oldInitialId !== checkpointData.initialValidatorSetId) { + logger.info( + ` initialValidatorSetId: ${oldInitialId ?? "unset"} -> ${checkpointData.initialValidatorSetId}` + ); + } + if (oldNextId !== checkpointData.nextValidatorSetId) { + logger.info( + ` nextValidatorSetId: ${oldNextId ?? "unset"} -> ${checkpointData.nextValidatorSetId}` + ); + } + if (JSON.stringify(oldInitial) !== JSON.stringify(checkpointData.initialValidatorHashes)) { + logger.info( + ` initialValidatorHashes: ${oldInitial.length} -> ${checkpointData.initialValidatorHashes.length} entries` + ); + } + if (JSON.stringify(oldNext) !== JSON.stringify(checkpointData.nextValidatorHashes)) { + logger.info( + ` nextValidatorHashes: ${oldNext.length} -> ${checkpointData.nextValidatorHashes.length} entries` + ); + } +}; + +/** + * Main handler for the update-beefy-checkpoint command. + * Fetches BEEFY authorities from a live DataHaven chain and updates the config file. + */ +export const updateBeefyCheckpoint = async ( + options: UpdateBeefyCheckpointOptions +): Promise => { + const networkId = buildNetworkId(options.chain, options.environment); + + printHeader(`Updating BEEFY Checkpoint for ${networkId}`); + + logger.info("📋 Configuration:"); + logger.info(` Chain: ${options.chain}`); + if (options.environment) { + logger.info(` Environment: ${options.environment}`); + } + logger.info(` RPC URL: ${options.rpcUrl}`); + logger.info(` Config file: contracts/config/${networkId}.json`); + + printDivider(); + + try { + // Fetch checkpoint data from the live chain + const checkpointData = await fetchBeefyCheckpointData(options.rpcUrl); + + printDivider(); + + // Display the checkpoint data + logger.info("📝 BEEFY Checkpoint Data:"); + logger.info(` Start Block: ${checkpointData.startBlock}`); + logger.info(` Min Required Signatures: ${checkpointData.minNumRequiredSignatures}`); + logger.info(` Initial Validator Set ID: ${checkpointData.initialValidatorSetId}`); + logger.info(` Initial Validators (${checkpointData.initialValidatorHashes.length} total):`); + for (let i = 0; i < checkpointData.initialValidatorHashes.length; i++) { + logger.info(` [${i}] ${checkpointData.initialValidatorHashes[i]}`); + } + + logger.info(` Next Validator Set ID: ${checkpointData.nextValidatorSetId}`); + logger.info(` Next Validators (${checkpointData.nextValidatorHashes.length} total):`); + for (let i = 0; i < checkpointData.nextValidatorHashes.length; i++) { + logger.info(` [${i}] ${checkpointData.nextValidatorHashes[i]}`); + } + + printDivider(); + + // Update the config file + await updateConfigFile(networkId, checkpointData); + + printDivider(); + logger.success(`BEEFY checkpoint updated successfully for ${networkId}`); + } catch (error) { + logger.error(`Failed to update BEEFY checkpoint: ${error}`); + throw error; + } +}; + +/** + * CLI action handler for the update-beefy-checkpoint command. + * Note: Chain and environment validation is handled by contractsPreActionHook. + */ +export const contractsUpdateBeefyCheckpoint = async ( + options: any, + _command: any +): Promise => { + const { chain, environment, rpcUrl } = options; + + // Validate rpc-url (specific to this command, not validated by preAction hook) + if (!rpcUrl) { + logger.error("❌ --rpc-url is required (WebSocket URL to the DataHaven chain)"); + process.exit(1); + } + + await updateBeefyCheckpoint({ + chain, + environment, + rpcUrl + }); +}; diff --git a/test/cli/handlers/contracts/deploy.ts b/test/cli/handlers/contracts/deploy.ts index b8dc71f4..1999d6e0 100644 --- a/test/cli/handlers/contracts/deploy.ts +++ b/test/cli/handlers/contracts/deploy.ts @@ -3,8 +3,15 @@ import { deployContracts } from "../../../scripts/deploy-contracts"; import { showDeploymentPlanAndStatus } from "./status"; import { verifyContracts } from "./verify"; -export const contractsDeploy = async (options: any, command: any) => { - // Try to get chain from options or command +/** + * Extracts chain and environment options from command options and parent command. + * This handles the case where options may be specified at either the subcommand + * or parent command level. + */ +const getChainAndEnvironment = ( + options: any, + command: any +): { chain: string | undefined; environment: string | undefined } => { let chain = options.chain; if (!chain && command.parent) { chain = command.parent.getOptionValue("chain"); @@ -13,19 +20,38 @@ export const contractsDeploy = async (options: any, command: any) => { chain = command.getOptionValue("chain"); } - printHeader(`Deploying DataHaven Contracts to ${chain}`); + let environment = options.environment; + if (!environment && command.parent) { + environment = command.parent.getOptionValue("environment"); + } + + return { chain, environment }; +}; + +export const contractsDeploy = async (options: any, command: any) => { + const { chain, environment } = getChainAndEnvironment(options, command); + + // Build display name for logging + const displayName = environment ? `${environment}-${chain}` : chain; + + printHeader(`Deploying DataHaven Contracts to ${displayName}`); const txExecutionOverride = options.executeOwnerTransactions ? true : undefined; try { logger.info("🚀 Starting deployment..."); logger.info(`📡 Using chain: ${chain}`); + if (environment) { + logger.info(`📡 Using environment: ${environment}`); + } if (options.rpcUrl) { logger.info(`📡 Using RPC URL: ${options.rpcUrl}`); } + // Chain is guaranteed to be defined by preAction hook validation await deployContracts({ - chain: chain, + chain: chain!, + environment: environment, rpcUrl: options.rpcUrl, privateKey: options.privateKey, avsOwnerKey: options.avsOwnerKey, @@ -40,34 +66,27 @@ export const contractsDeploy = async (options: any, command: any) => { }; export const contractsCheck = async (options: any, command: any) => { - // Try to get chain from options or command - let chain = options.chain; - if (!chain && command.parent) { - chain = command.parent.getOptionValue("chain"); - } - if (!chain) { - chain = command.getOptionValue("chain"); - } + const { chain, environment } = getChainAndEnvironment(options, command); - printHeader(`Checking DataHaven ${chain} Configuration and Status`); + // Build network identifier with environment prefix if specified + const networkId = environment ? `${environment}-${chain}` : chain; + + printHeader(`Checking DataHaven ${networkId} Configuration and Status`); logger.info("🔍 Showing deployment plan and status"); // Use the status function from status.ts - await showDeploymentPlanAndStatus(chain); + // Chain is guaranteed to be defined by preAction hook validation + await showDeploymentPlanAndStatus(chain!, environment); }; export const contractsVerify = async (options: any, command: any) => { - // Try to get chain from options or command - let chain = options.chain; - if (!chain && command.parent) { - chain = command.parent.getOptionValue("chain"); - } - if (!chain) { - chain = command.getOptionValue("chain"); - } + const { chain, environment } = getChainAndEnvironment(options, command); - printHeader(`Verifying DataHaven Contracts on ${chain} Block Explorer`); + // Build display name for logging + const displayName = environment ? `${environment}-${chain}` : chain; + + printHeader(`Verifying DataHaven Contracts on ${displayName} Block Explorer`); if (options.skipVerification) { logger.info("⏭️ Skipping verification as requested"); @@ -77,7 +96,8 @@ export const contractsVerify = async (options: any, command: any) => { try { const verifyOptions = { ...options, - chain: chain + chain: chain, + environment: environment }; await verifyContracts(verifyOptions); printDivider(); @@ -86,26 +106,63 @@ export const contractsVerify = async (options: any, command: any) => { } }; +/** + * Supported networks for contract deployment. + * These must correspond to config files in contracts/config/{network}.json + */ +export const SUPPORTED_NETWORKS = [ + "anvil", + "hoodi", + "stagenet-hoodi", + "testnet-hoodi", + "ethereum", + "mainnet-ethereum" +] as const; + export const contractsPreActionHook = async (thisCommand: any) => { let chain = thisCommand.getOptionValue("chain"); + let environment = thisCommand.getOptionValue("environment"); if (!chain && thisCommand.parent) { chain = thisCommand.parent.getOptionValue("chain"); } + if (!environment && thisCommand.parent) { + environment = thisCommand.parent.getOptionValue("environment"); + } const privateKey = thisCommand.getOptionValue("privateKey"); if (!chain) { - logger.error("❌ Chain is required. Use --chain option (hoodi, mainnet, anvil)"); + logger.error("❌ Chain is required. Use --chain option (hoodi, ethereum, anvil)"); process.exit(1); } - const supportedChains = ["hoodi", "mainnet", "anvil"]; + const supportedChains = ["hoodi", "ethereum", "anvil"]; if (!supportedChains.includes(chain)) { logger.error(`❌ Unsupported chain: ${chain}. Supported chains: ${supportedChains.join(", ")}`); process.exit(1); } + // Validate environment if provided + if (environment) { + const supportedEnvironments = ["stagenet", "testnet", "mainnet"]; + if (!supportedEnvironments.includes(environment)) { + logger.error( + `❌ Unsupported environment: ${environment}. Supported environments: ${supportedEnvironments.join(", ")}` + ); + process.exit(1); + } + + // Validate the full network identifier exists + const networkId = `${environment}-${chain}`; + if (!SUPPORTED_NETWORKS.includes(networkId as (typeof SUPPORTED_NETWORKS)[number])) { + logger.error( + `❌ Unsupported network combination: ${networkId}. Supported networks: ${SUPPORTED_NETWORKS.join(", ")}` + ); + process.exit(1); + } + } + if (!privateKey && !process.env.DEPLOYER_PRIVATE_KEY) { logger.warn( "⚠️ Private key not provided. Will use DEPLOYER_PRIVATE_KEY environment variable if set, or default Anvil key." diff --git a/test/cli/handlers/contracts/index.ts b/test/cli/handlers/contracts/index.ts index 681b6d8e..b0596e2b 100644 --- a/test/cli/handlers/contracts/index.ts +++ b/test/cli/handlers/contracts/index.ts @@ -1,4 +1,6 @@ +export * from "./beefy-checkpoint"; export * from "./deploy"; +export * from "./rewards-origin"; export * from "./status"; export * from "./update-metadata"; export * from "./verify"; diff --git a/test/cli/handlers/contracts/rewards-origin.ts b/test/cli/handlers/contracts/rewards-origin.ts new file mode 100644 index 00000000..d89c31bd --- /dev/null +++ b/test/cli/handlers/contracts/rewards-origin.ts @@ -0,0 +1,327 @@ +import invariant from "tiny-invariant"; +import { logger, printDivider, printHeader } from "utils"; +import { createPapiConnectors } from "utils/papi"; +import { concat, type Hex, toBytes, toHex } from "viem"; +import { buildNetworkId } from "../../../configs/contracts/config"; + +interface UpdateRewardsOriginOptions { + chain: string; + environment?: string; + rpcUrl: string; + genesisHash?: string; +} + +/** + * Derives an AccountId20 from a PalletId using the same algorithm as Substrate's + * `into_account_truncating()`. + * + * The algorithm (see https://www.shawntabrizi.com/substrate-js-utilities/): + * 1. Prepends "modl" (4 bytes) to the 8-byte pallet ID + * 2. For AccountId20 (H160), takes the first 20 bytes: modl(4) + pallet_id(8) + zeros(8) + * + * Note: This is a simple truncation, NOT a hash operation. + * + * @param palletId - The 8-character pallet ID string (e.g., "dh/evrew") + * @returns The derived AccountId20 as a hex string + */ +const palletIdToAccountId20 = (palletId: string): Hex => { + invariant(palletId.length === 8, "Pallet ID must be exactly 8 characters"); + + // Build: "modl" (4 bytes) + pallet_id (8 bytes) + zeros (8 bytes) = 20 bytes + const prefix = toBytes("modl"); + const palletIdBytes = toBytes(palletId); + const accountId20 = new Uint8Array(20); + accountId20.set(prefix, 0); + accountId20.set(palletIdBytes, 4); + // Remaining 8 bytes are already zeros (padding) + + return toHex(accountId20); +}; + +/** + * Computes the Agent ID (H256) for a pallet's sovereign account on the DataHaven chain. + * + * The Agent ID is computed following Snowbridge's `AgentIdOf` type, which uses + * `HashedDescription` with `DescribeGlobalPrefix`. For an AccountKey20 on a chain + * identified by its genesis hash, the encoding is: + * + * blake2_256(SCALE_ENCODE(("GlobalConsensus", ByGenesis(genesis_hash), ("AccountKey20", account_key)))) + * + * NOTE: This computation follows Snowbridge's pattern but may need verification against + * the actual on-chain Agent ID. The preferred approach is to set RewardsAgentOrigin on + * the chain and fetch it via this command. + * + * @param genesisHash - The chain's genesis hash (32 bytes, hex string with 0x prefix) + * @param accountKey20 - The 20-byte account key (hex string with 0x prefix) + * @returns The computed Agent ID as a hex string + */ +const computeAgentId = async (genesisHash: Hex, accountKey20: Hex): Promise => { + // Import blake2b dynamically (it's an ESM module) + const { blake2b } = await import("@noble/hashes/blake2b"); + + // Validate inputs + invariant( + genesisHash.length === 66, + `Genesis hash must be 32 bytes (66 chars with 0x prefix), got ${genesisHash.length}` + ); + invariant( + accountKey20.length === 42, + `Account key must be 20 bytes (42 chars with 0x prefix), got ${accountKey20.length}` + ); + + // SCALE encoding for the location description follows Snowbridge's pattern: + // ("GlobalConsensus", ByGenesis(genesis_hash), interior_description) + // + // Where interior_description for AccountKey20 is: + // ("AccountKey20", key) + // + // In SCALE for fixed-size arrays (like b"GlobalConsensus"): + // - Fixed-size byte arrays are encoded as raw bytes without length prefix + // - Variable-length Vec gets a compact length prefix + // - Enums are encoded as variant index + payload + + // "GlobalConsensus" as raw bytes (15 bytes, no length prefix for fixed array) + const globalConsensusBytes = toBytes("GlobalConsensus"); + + // ByGenesis variant (index 0 in NetworkId enum) + genesis hash (32 bytes) + // NetworkId::ByGenesis is the first variant, so index = 0 + const byGenesisVariant = new Uint8Array([0]); + const genesisBytes = toBytes(genesisHash); + + // "AccountKey20" as raw bytes (12 bytes, no length prefix for fixed array) + const accountKey20StrBytes = toBytes("AccountKey20"); + + // Account key bytes (20 bytes) + const accountKeyBytes = toBytes(accountKey20); + + // Build the interior description: ("AccountKey20", key) as raw bytes + const interiorDescription = concat([accountKey20StrBytes, accountKeyBytes]); + + // Length prefix for interior (SCALE compact encoding: value << 2 for values < 64) + const interiorLen = interiorDescription.length; + const interiorLenCompact = new Uint8Array([interiorLen << 2]); + + // Final encoding: GlobalConsensus prefix + ByGenesis(genesis) + compact_len(interior) + const encoded = concat([ + globalConsensusBytes, + byGenesisVariant, + genesisBytes, + interiorLenCompact, + interiorDescription + ]); + + // Hash with blake2b-256 to get the Agent ID (same as Snowbridge's blake2_256) + const hash = blake2b(new Uint8Array(encoded), { dkLen: 32 }); + return toHex(hash); +}; + +/** + * Fetches the RewardsAgentOrigin from the runtime parameters. + * + * @param rpcUrl - WebSocket RPC endpoint of the DataHaven chain + * @returns The RewardsAgentOrigin as a hex string, or null if not set or zero + */ +const fetchRewardsAgentOrigin = async (rpcUrl: string): Promise => { + logger.info(`📡 Connecting to DataHaven chain at ${rpcUrl}...`); + + const { client: papiClient, typedApi: dhApi } = createPapiConnectors(rpcUrl); + + try { + logger.info("🔍 Fetching RewardsAgentOrigin from runtime parameters..."); + + // Query the Parameters pallet for RewardsAgentOrigin + const parameter = await dhApi.query.Parameters.Parameters.getValue( + { + type: "RuntimeConfig", + value: { type: "RewardsAgentOrigin", value: undefined } + }, + { at: "best" } + ); + + if (!parameter) { + logger.info("ℹ️ RewardsAgentOrigin parameter not found (using default)"); + return null; + } + + // Extract the value from the parameter result + // The parameter is wrapped in the RuntimeConfig enum variant + if (parameter.type === "RuntimeConfig" && parameter.value.type === "RewardsAgentOrigin") { + const origin = parameter.value.value; + if (origin) { + const originHex = origin.asHex(); + // Check if it's the zero hash + const zeroHash = + "0x0000000000000000000000000000000000000000000000000000000000000000" as Hex; + if (originHex === zeroHash) { + logger.info("ℹ️ RewardsAgentOrigin is set to zero (placeholder)"); + return null; + } + logger.success(`Found RewardsAgentOrigin: ${originHex}`); + return originHex as Hex; + } + } + + logger.info("ℹ️ RewardsAgentOrigin value not available"); + return null; + } finally { + papiClient.destroy(); + } +}; + +/** + * Fetches the genesis hash from the chain. + * + * @param rpcUrl - WebSocket RPC endpoint of the DataHaven chain + * @returns The genesis hash as a hex string + */ +const fetchGenesisHash = async (rpcUrl: string): Promise => { + logger.info("🔍 Fetching genesis hash from chain..."); + + const { client: papiClient } = createPapiConnectors(rpcUrl); + + try { + // Use _request to call chain_getBlockHash RPC method with block number 0 + const genesisHash = await papiClient._request("chain_getBlockHash", [0]); + logger.success(`Genesis hash: ${genesisHash}`); + return genesisHash as Hex; + } finally { + papiClient.destroy(); + } +}; + +/** + * Updates the config file with the rewards message origin. + * + * @param networkId - The network identifier (e.g., "hoodi", "stagenet-hoodi") + * @param rewardsMessageOrigin - The rewards message origin (Agent ID) + */ +const updateConfigFile = async (networkId: string, rewardsMessageOrigin: Hex): Promise => { + const configFilePath = `../contracts/config/${networkId}.json`; + const configFile = Bun.file(configFilePath); + + if (!(await configFile.exists())) { + throw new Error(`Configuration file not found: ${configFilePath}`); + } + + const configContent = await configFile.text(); + const configJson = JSON.parse(configContent); + + if (!configJson.snowbridge) { + logger.warn(`"snowbridge" section not found in config, creating it.`); + configJson.snowbridge = {}; + } + + const oldOrigin = configJson.snowbridge.rewardsMessageOrigin; + configJson.snowbridge.rewardsMessageOrigin = rewardsMessageOrigin; + + await Bun.write(configFilePath, `${JSON.stringify(configJson, null, 2)}\n`); + + logger.success(`Config file updated: ${configFilePath}`); + + if (oldOrigin !== rewardsMessageOrigin) { + logger.info(` rewardsMessageOrigin: ${oldOrigin ?? "unset"} -> ${rewardsMessageOrigin}`); + } +}; + +/** + * Main handler for the update-rewards-origin command. + * Fetches or computes the RewardsAgentOrigin and updates the config file. + */ +export const updateRewardsOrigin = async (options: UpdateRewardsOriginOptions): Promise => { + const networkId = buildNetworkId(options.chain, options.environment); + + printHeader(`Updating Rewards Message Origin for ${networkId}`); + + logger.info("📋 Configuration:"); + logger.info(` Chain: ${options.chain}`); + if (options.environment) { + logger.info(` Environment: ${options.environment}`); + } + logger.info(` RPC URL: ${options.rpcUrl}`); + if (options.genesisHash) { + logger.info(` Genesis hash (provided): ${options.genesisHash}`); + } + logger.info(` Config file: contracts/config/${networkId}.json`); + + printDivider(); + + try { + // Step 1: Try to fetch RewardsAgentOrigin from the chain + let rewardsMessageOrigin = await fetchRewardsAgentOrigin(options.rpcUrl); + + printDivider(); + + if (rewardsMessageOrigin) { + // Use the value from the chain + logger.info("✅ Using RewardsAgentOrigin from chain runtime parameters"); + } else { + // Compute the Agent ID from genesis hash and pallet account + logger.info("🔧 Computing RewardsAgentOrigin from genesis hash and pallet account..."); + + // Get genesis hash (from option or fetch from chain) + const genesisHash = options.genesisHash + ? (options.genesisHash as Hex) + : await fetchGenesisHash(options.rpcUrl); + + // Derive the ExternalValidatorRewardsAccount from the pallet ID "dh/evrew" + const palletId = "dh/evrew"; + logger.info(`🔐 Deriving account from pallet ID: "${palletId}"`); + const rewardsAccount = palletIdToAccountId20(palletId); + logger.info(` Rewards pallet account: ${rewardsAccount}`); + + // Compute the Agent ID + logger.info("🔐 Computing Agent ID..."); + logger.warn( + "⚠️ Note: Computed Agent ID may need verification. Prefer setting RewardsAgentOrigin on-chain." + ); + rewardsMessageOrigin = await computeAgentId(genesisHash, rewardsAccount); + logger.info(` Agent ID: ${rewardsMessageOrigin}`); + } + + printDivider(); + + // Display the final value + logger.info("📝 Rewards Message Origin:"); + logger.info(` ${rewardsMessageOrigin}`); + + printDivider(); + + // Update the config file + await updateConfigFile(networkId, rewardsMessageOrigin); + + printDivider(); + logger.success(`Rewards message origin updated successfully for ${networkId}`); + } catch (error) { + logger.error(`Failed to update rewards message origin: ${error}`); + throw error; + } +}; + +/** + * CLI action handler for the update-rewards-origin command. + * Note: Chain and environment validation is handled by contractsPreActionHook. + */ +export const contractsUpdateRewardsOrigin = async (options: any, _command: any): Promise => { + const { chain, environment, rpcUrl, genesisHash } = options; + + // Validate rpc-url (specific to this command, not validated by preAction hook) + if (!rpcUrl) { + logger.error("❌ --rpc-url is required (WebSocket URL to the DataHaven chain)"); + process.exit(1); + } + + // Validate genesis hash format if provided + if (genesisHash) { + if (!/^0x[0-9a-fA-F]{64}$/.test(genesisHash)) { + logger.error("❌ --genesis-hash must be a 32-byte hex string (0x + 64 hex chars)"); + process.exit(1); + } + } + + await updateRewardsOrigin({ + chain, + environment, + rpcUrl, + genesisHash + }); +}; diff --git a/test/cli/handlers/contracts/status.ts b/test/cli/handlers/contracts/status.ts index a6d34e05..3c61e04b 100644 --- a/test/cli/handlers/contracts/status.ts +++ b/test/cli/handlers/contracts/status.ts @@ -1,37 +1,49 @@ import { logger, printDivider } from "utils"; -import { getChainDeploymentParams, loadChainConfig } from "../../../configs/contracts/config"; +import { + buildNetworkId, + getChainDeploymentParams, + loadChainConfig +} from "../../../configs/contracts/config"; import { checkContractVerification } from "./verify"; /** * Shows the status of chain deployment and verification + * @param chain - The target chain (hoodi, mainnet, anvil) + * @param environment - Optional deployment environment (stagenet, testnet, mainnet) */ -export const showDeploymentPlanAndStatus = async (chain: string) => { +export const showDeploymentPlanAndStatus = async (chain: string, environment?: string) => { + const networkId = buildNetworkId(chain, environment); + try { - const config = await loadChainConfig(chain); + const config = await loadChainConfig(chain, environment); const deploymentParams = getChainDeploymentParams(chain); - const displayData = { + const displayData: Record = { Network: `${deploymentParams.network} (Chain ID: ${deploymentParams.chainId})`, "RPC URL": deploymentParams.rpcUrl, "Block Explorer": deploymentParams.blockExplorer, "Genesis Time": new Date(deploymentParams.genesisTime * 1000).toISOString(), "AVS Owner": `${config.avs.avsOwner.slice(0, 10)}...${config.avs.avsOwner.slice(-8)}`, - "Rewards Initiator": `${config.avs.rewardsInitiator.slice(0, 10)}...${config.avs.rewardsInitiator.slice(-8)}`, - "Veto Committee Member": `${config.avs.vetoCommitteeMember.slice(0, 10)}...${config.avs.vetoCommitteeMember.slice(-8)}` + "Rewards Initiator": `${config.avs.rewardsInitiator.slice(0, 10)}...${config.avs.rewardsInitiator.slice(-8)}` }; + + if (environment) { + displayData.Environment = environment; + } + console.table(displayData); - await showDatahavenContractStatus(chain, deploymentParams.rpcUrl); + await showDatahavenContractStatus(networkId, deploymentParams.rpcUrl); await showEigenLayerContractStatus( config, deploymentParams.chainId.toString(), deploymentParams.rpcUrl, - chain + networkId ); printDivider(); } catch (error) { - logger.error(`❌ Failed to load ${chain} configuration: ${error}`); + logger.error(`❌ Failed to load ${networkId} configuration: ${error}`); } }; @@ -69,8 +81,10 @@ const printContractStatus = async ( /** * Shows the status of all contracts (deployment + verification) + * @param networkId - The network identifier (e.g., "hoodi", "stagenet-hoodi") + * @param rpcUrl - The RPC URL for the chain */ -const showDatahavenContractStatus = async (chain: string, rpcUrl: string) => { +const showDatahavenContractStatus = async (networkId: string, rpcUrl: string) => { try { const contracts = [ { name: "DataHavenServiceManager", key: "ServiceManagerImplementation" }, @@ -81,7 +95,7 @@ const showDatahavenContractStatus = async (chain: string, rpcUrl: string) => { logger.info("DataHaven contracts"); - const deploymentsPath = `../contracts/deployments/${chain}.json`; + const deploymentsPath = `../contracts/deployments/${networkId}.json`; const deploymentsFile = Bun.file(deploymentsPath); const exists = await deploymentsFile.exists(); @@ -97,7 +111,12 @@ const showDatahavenContractStatus = async (chain: string, rpcUrl: string) => { for (const contract of contracts) { const address = deployments[contract.key]; - await printContractStatus({ name: contract.name, address }, etherscanApiKey, chain, rpcUrl); + await printContractStatus( + { name: contract.name, address }, + etherscanApiKey, + networkId, + rpcUrl + ); } } catch (error) { logger.warn(`⚠️ Could not check contract status: ${error}`); @@ -106,22 +125,26 @@ const showDatahavenContractStatus = async (chain: string, rpcUrl: string) => { /** * Shows the status of EigenLayer contracts (verification only) + * @param config - The chain configuration + * @param chainId - The chain ID + * @param rpcUrl - The RPC URL for the chain + * @param networkId - The network identifier (e.g., "hoodi", "stagenet-hoodi") */ const showEigenLayerContractStatus = async ( config: any, chainId: string, rpcUrl: string, - chain: string + networkId: string ) => { try { // For local/anvil deployments, read addresses from deployments file // For testnet/mainnet, use addresses from config file let eigenLayerAddresses: Record = {}; - const isLocal = chain === "anvil" || chain === "local"; + const isLocal = networkId === "anvil" || networkId === "local"; if (isLocal) { try { - const deploymentsPath = `../contracts/deployments/${chain === "local" ? "anvil" : chain}.json`; + const deploymentsPath = `../contracts/deployments/${networkId === "local" ? "anvil" : networkId}.json`; const deploymentsFile = Bun.file(deploymentsPath); if (await deploymentsFile.exists()) { const deployments = await deploymentsFile.json(); diff --git a/test/cli/handlers/contracts/update-metadata.ts b/test/cli/handlers/contracts/update-metadata.ts index d6f49cba..5c7e50b2 100644 --- a/test/cli/handlers/contracts/update-metadata.ts +++ b/test/cli/handlers/contracts/update-metadata.ts @@ -1,7 +1,7 @@ import { logger, parseDeploymentsFile, printDivider } from "utils"; import { createPublicClient, createWalletClient, encodeFunctionData, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; -import { getChainDeploymentParams } from "../../../configs/contracts/config"; +import { buildNetworkId, getChainDeploymentParams } from "../../../configs/contracts/config"; import { dataHavenServiceManagerAbi } from "../../../contract-bindings/generated"; /** @@ -10,7 +10,7 @@ import { dataHavenServiceManagerAbi } from "../../../contract-bindings/generated export const updateAVSMetadataURI = async ( chain: string, uri: string, - opts: { execute?: boolean; avsOwnerKey?: string } = {} + opts: { execute?: boolean; avsOwnerKey?: string; environment?: string } = {} ) => { try { const execute = opts.execute ?? false; @@ -22,14 +22,15 @@ export const updateAVSMetadataURI = async ( throw new Error("AVS owner private key is required to execute this transaction"); } - // Get chain configuration + // Get chain configuration using base chain name, and build networkId for deployment file lookup + const networkId = buildNetworkId(chain, opts.environment); const deploymentParams = getChainDeploymentParams(chain); - logger.info(`🫎 Updating AVS metadata URI on ${chain} chain`); + logger.info(`🫎 Updating AVS metadata URI on ${networkId}`); logger.info(`Network: ${deploymentParams.network} (Chain ID: ${deploymentParams.chainId})`); logger.info(`RPC URL: ${deploymentParams.rpcUrl}`); logger.info(`New URI: ${uri}`); - const deployments = await parseDeploymentsFile(chain); + const deployments = await parseDeploymentsFile(networkId); const serviceManagerAddress = deployments.ServiceManager; if (!serviceManagerAddress) { diff --git a/test/cli/handlers/contracts/verify.ts b/test/cli/handlers/contracts/verify.ts index 063ec23e..5d6bf98b 100644 --- a/test/cli/handlers/contracts/verify.ts +++ b/test/cli/handlers/contracts/verify.ts @@ -1,10 +1,11 @@ import { execSync } from "node:child_process"; import { logger } from "utils"; import { parseDeploymentsFile } from "utils/contracts"; -import { CHAIN_CONFIGS, getChainConfig } from "../../../configs/contracts/config"; +import { buildNetworkId, CHAIN_CONFIGS, getChainConfig } from "../../../configs/contracts/config"; interface ContractsVerifyOptions { chain: string; + environment?: string; rpcUrl?: string; skipVerification: boolean; } @@ -13,8 +14,12 @@ interface ContractToVerify { name: string; address: string; artifactName: string; + /** Path to the contract source file relative to the contracts directory (e.g. "src/Foo.sol" or "lib/snowbridge/contracts/src/Bar.sol") */ + contractPath: string; constructorArgs: string[]; constructorArgTypes: string[]; + /** When true, uses forge's --guess-constructor-args instead of explicit args (useful for proxies with complex init data) */ + guessConstructorArgs?: boolean; } /** @@ -26,7 +31,10 @@ export const verifyContracts = async (options: ContractsVerifyOptions) => { return; } - logger.info(`🔍 Verifying contracts on ${options.chain} block explorer using Foundry...`); + // Build network identifier for deployment file lookup + const networkId = buildNetworkId(options.chain, options.environment); + + logger.info(`🔍 Verifying contracts on ${networkId} block explorer using Foundry...`); const etherscanApiKey = process.env.ETHERSCAN_API_KEY; if (!etherscanApiKey) { @@ -35,13 +43,19 @@ export const verifyContracts = async (options: ContractsVerifyOptions) => { return; } - const deployments = await parseDeploymentsFile(options.chain); + const deployments = await parseDeploymentsFile(networkId); + + // Resolve the Gateway implementation address from the ERC1967 proxy storage slot + const chainConfig = CHAIN_CONFIGS[options.chain as keyof typeof CHAIN_CONFIGS]; + const rpcUrl = options.rpcUrl || chainConfig.RPC_URL; + const gatewayImplAddress = await getProxyImplementation(deployments.Gateway, rpcUrl); const contractsToVerify: ContractToVerify[] = [ { name: "ServiceManager Implementation", address: deployments.ServiceManagerImplementation, artifactName: "DataHavenServiceManager", + contractPath: "src/DataHavenServiceManager.sol", constructorArgs: [ deployments.RewardsCoordinator, deployments.PermissionController, @@ -50,16 +64,41 @@ export const verifyContracts = async (options: ContractsVerifyOptions) => { constructorArgTypes: ["address", "address", "address"] }, { - name: "Gateway", - address: deployments.Gateway, - artifactName: "Gateway", + name: "ServiceManager Proxy", + address: deployments.ServiceManager, + artifactName: "TransparentUpgradeableProxy", + contractPath: + "lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/contracts/proxy/transparent/TransparentUpgradeableProxy.sol", constructorArgs: [], - constructorArgTypes: [] + constructorArgTypes: [], + guessConstructorArgs: true + }, + ...(gatewayImplAddress + ? [ + { + name: "Gateway Implementation", + address: gatewayImplAddress, + artifactName: "Gateway", + contractPath: "lib/snowbridge/contracts/src/Gateway.sol", + constructorArgs: [deployments.BeefyClient, deployments.AgentExecutor], + constructorArgTypes: ["address", "address"] + } + ] + : []), + { + name: "Gateway Proxy", + address: deployments.Gateway, + artifactName: "GatewayProxy", + contractPath: "lib/snowbridge/contracts/src/GatewayProxy.sol", + constructorArgs: [], + constructorArgTypes: [], + guessConstructorArgs: true }, { name: "BeefyClient", address: deployments.BeefyClient, artifactName: "BeefyClient", + contractPath: "lib/snowbridge/contracts/src/BeefyClient.sol", constructorArgs: [], constructorArgTypes: [] }, @@ -67,11 +106,18 @@ export const verifyContracts = async (options: ContractsVerifyOptions) => { name: "AgentExecutor", address: deployments.AgentExecutor, artifactName: "AgentExecutor", + contractPath: "lib/snowbridge/contracts/src/AgentExecutor.sol", constructorArgs: [], constructorArgTypes: [] } ]; + if (!gatewayImplAddress) { + logger.warn( + "⚠️ Could not resolve Gateway implementation address from proxy, skipping Gateway implementation verification" + ); + } + try { logger.info("📋 Contracts to verify:"); contractsToVerify.forEach((contract) => { @@ -105,17 +151,29 @@ export const verifyContracts = async (options: ContractsVerifyOptions) => { async function verifySingleContract(contract: ContractToVerify, options: ContractsVerifyOptions) { logger.info(`\n🔍 Verifying ${contract.name} (${contract.address})...`); - const { address, artifactName, constructorArgs: args, constructorArgTypes: types } = contract; + const { + address, + artifactName, + contractPath, + constructorArgs: args, + constructorArgTypes: types, + guessConstructorArgs + } = contract; - const abiEncodedArgs = getEncodedConstructorArgs(args, types); - const constructorArgsStr = abiEncodedArgs ? `--constructor-args ${abiEncodedArgs}` : ""; + let constructorArgsStr: string; + if (guessConstructorArgs) { + constructorArgsStr = "--guess-constructor-args"; + } else { + const abiEncodedArgs = getEncodedConstructorArgs(args, types); + constructorArgsStr = abiEncodedArgs ? `--constructor-args ${abiEncodedArgs}` : ""; + } try { const chainConfig = CHAIN_CONFIGS[options.chain as keyof typeof CHAIN_CONFIGS]; const rpcUrl = options.rpcUrl || chainConfig.RPC_URL; const chainParameter = options.chain === "hoodi" ? "--chain-id 560048" : `--chain ${options.chain}`; - const verifyCommand = `forge verify-contract ${address} src/${artifactName}.sol:${artifactName} --rpc-url ${rpcUrl} ${chainParameter} ${constructorArgsStr} --watch`; + const verifyCommand = `forge verify-contract ${address} ${contractPath}:${artifactName} --rpc-url ${rpcUrl} ${chainParameter} ${constructorArgsStr} --watch`; logger.info(`Running: ${verifyCommand}`); @@ -138,7 +196,7 @@ async function verifySingleContract(contract: ContractToVerify, options: Contrac logger.info(`Check manually at: ${chainConfig.BLOCK_EXPLORER}address/${contract.address}`); logger.info("You can also try running the command manually from the contracts directory:"); const rpcUrl = options.rpcUrl || chainConfig.RPC_URL; - const manualCommand = `forge verify-contract ${contract.address} src/${contract.artifactName}.sol:${contract.artifactName} --rpc-url ${rpcUrl} --chain ${options.chain} ${constructorArgsStr}`; + const manualCommand = `forge verify-contract ${contract.address} ${contract.contractPath}:${contract.artifactName} --rpc-url ${rpcUrl} --chain ${options.chain} ${constructorArgsStr}`; logger.info(`cd ../contracts && ${manualCommand}`); } } diff --git a/test/cli/handlers/launch/index.ts b/test/cli/handlers/launch/index.ts index 922a16da..a6f90f51 100644 --- a/test/cli/handlers/launch/index.ts +++ b/test/cli/handlers/launch/index.ts @@ -13,7 +13,7 @@ import { setParametersFromCollection } from "./parameters"; import { launchRelayers } from "./relayer"; import { launchStorageHubComponents } from "./storagehub"; import { performSummaryOperations } from "./summary"; -import { performValidatorOperations } from "./validator"; +import { performValidatorOperations, performValidatorSetUpdate } from "./validator"; export const NETWORK_ID = "cli-launch"; @@ -43,6 +43,7 @@ export interface LaunchOptions { deployContracts?: boolean; fundValidators?: boolean; setupValidators?: boolean; + updateValidatorSet?: boolean; setParameters?: boolean; relayer?: boolean; relayerImageTag: string; @@ -84,8 +85,9 @@ const launchFunction = async (options: LaunchOptions, launchedNetwork: LaunchedN } // skip deploying contracts if we have injected it + let contractsDeployed = false; if (options.deployContracts && !options.injectContracts) { - const contractsDeployed = await deployContracts({ + contractsDeployed = await deployContracts({ rpcUrl: launchedNetwork.elRpcUrl, verified: options.verified, blockscoutBackendUrl, @@ -107,6 +109,8 @@ const launchFunction = async (options: LaunchOptions, launchedNetwork: LaunchedN await launchRelayers(options, launchedNetwork); + await performValidatorSetUpdate(options, launchedNetwork.elRpcUrl, contractsDeployed); + await launchStorageHubComponents(options, launchedNetwork); await performSummaryOperations(options, launchedNetwork); diff --git a/test/cli/handlers/launch/storagehub.ts b/test/cli/handlers/launch/storagehub.ts index fc162dde..51eca67e 100644 --- a/test/cli/handlers/launch/storagehub.ts +++ b/test/cli/handlers/launch/storagehub.ts @@ -1,6 +1,7 @@ import { logger, printHeader } from "utils"; import type { DataHavenOptions } from "../../../launcher/datahaven"; import { + launchBackend, launchBspNode, launchFishermanNode, launchIndexerNode, @@ -99,5 +100,9 @@ async function launchStorageHubDocker( logger.info("📝 Registering providers..."); await registerProviders({ launchedNetwork }); + // Launch Backend MSP + logger.info("📦 Launching StorageHub Backend..."); + await launchBackend(datahavenOptions, launchedNetwork); + logger.success("All StorageHub components launched and registered"); } diff --git a/test/cli/handlers/launch/validator.ts b/test/cli/handlers/launch/validator.ts index bcfa071a..6cdb901c 100644 --- a/test/cli/handlers/launch/validator.ts +++ b/test/cli/handlers/launch/validator.ts @@ -75,11 +75,31 @@ export const performValidatorOperations = async ( * @returns Promise resolving when the operation is complete */ export const performValidatorSetUpdate = async ( + options: LaunchOptions, networkRpcUrl: string, contractsDeployed: boolean ) => { printHeader("Updating DataHaven Validator Set"); + let shouldUpdateValidatorSet = options.updateValidatorSet; + if (shouldUpdateValidatorSet === undefined) { + shouldUpdateValidatorSet = await confirmWithTimeout( + "Do you want to update the validator set?", + true, + 10 + ); + } else { + logger.info( + `🏳️ Using flag option: ${shouldUpdateValidatorSet ? "will update" : "will not update"} validator set` + ); + } + + if (!shouldUpdateValidatorSet) { + logger.info("👍 Skipping validator set update"); + printDivider(); + return; + } + if (!contractsDeployed) { logger.warn( "⚠️ Updating validator set but contracts were not deployed in this CLI run. Could have unexpected results." diff --git a/test/cli/index.ts b/test/cli/index.ts index b0ee5c10..71ad8781 100644 --- a/test/cli/index.ts +++ b/test/cli/index.ts @@ -5,6 +5,8 @@ import { contractsCheck, contractsDeploy, contractsPreActionHook, + contractsUpdateBeefyCheckpoint, + contractsUpdateRewardsOrigin, contractsVerify, deploy, deployPreActionHook, @@ -199,15 +201,20 @@ const contractsCommand = program .addHelpText( "before", `🫎 DataHaven: Contracts Deployment CLI for deploying DataHaven AVS contracts to supported chains - + Commands: - status: Show deployment plan, configuration, and status (default) - deploy: Deploy contracts to specified chain - verify: Verify deployed contracts on block explorer + - update-beefy-checkpoint: Fetch BEEFY authorities from a live chain and update config + - update-rewards-origin: Fetch or compute the RewardsAgentOrigin and update config - update-metadata: Update the metadata URI of an existing AVS contract - + Common options: - --chain: Target chain (required: hoodi, mainnet, anvil) + --chain: Target chain (required: hoodi, ethereum, anvil) + --environment: Deployment environment (stagenet, testnet, mainnet) + When specified, config files are read from {environment}-{chain}.json + and deployments are written to {environment}-{chain}.json --rpc-url: Chain RPC URL (optional, defaults based on chain) --private-key: Private key for deployment --skip-verification: Skip contract verification @@ -219,7 +226,11 @@ const contractsCommand = program contractsCommand .command("status") .description("Show deployment plan, configuration, and status") - .option("--chain ", "Target chain (hoodi, mainnet, anvil)") + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) .option("--rpc-url ", "Chain RPC URL (optional, defaults based on chain)") .option( "--private-key ", @@ -234,7 +245,11 @@ contractsCommand contractsCommand .command("deploy") .description("Deploy DataHaven AVS contracts to specified chain") - .option("--chain ", "Target chain (hoodi, mainnet, anvil)") + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) .option("--rpc-url ", "Chain RPC URL (optional, defaults based on chain)") .option( "--private-key ", @@ -255,17 +270,73 @@ contractsCommand contractsCommand .command("verify") .description("Verify deployed contracts on block explorer") - .option("--chain ", "Target chain (hoodi, mainnet, anvil)") + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) .option("--rpc-url ", "Chain RPC URL (optional, defaults based on chain)") .option("--skip-verification", "Skip contract verification", false) .hook("preAction", contractsPreActionHook) .action(contractsVerify); +// Contracts Update BEEFY Checkpoint +contractsCommand + .command("update-beefy-checkpoint") + .description( + "Fetch BEEFY authorities from a live DataHaven chain and update the config file with validator hashes" + ) + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) + .option( + "--rpc-url ", + "WebSocket RPC URL of the DataHaven chain to fetch BEEFY authorities from" + ) + .hook("preAction", contractsPreActionHook) + .action(async (_options: any, command: any) => { + // Options are captured by parent command due to shared option names + // Use optsWithGlobals() to get all options including inherited ones + const opts = command.optsWithGlobals(); + await contractsUpdateBeefyCheckpoint(opts, command); + }); + +// Contracts Update Rewards Origin +contractsCommand + .command("update-rewards-origin") + .description( + "Fetch or compute the RewardsAgentOrigin and update the config file with the rewards message origin" + ) + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) + .option( + "--rpc-url ", + "WebSocket RPC URL of the DataHaven chain to fetch RewardsAgentOrigin from" + ) + .option( + "--genesis-hash ", + "Chain genesis hash (32 bytes hex). If not provided, will be fetched from the chain." + ) + .hook("preAction", contractsPreActionHook) + .action(async (_options: any, command: any) => { + const opts = command.optsWithGlobals(); + await contractsUpdateRewardsOrigin(opts, command); + }); + // Contracts Update Metadata contractsCommand .command("update-metadata") .description("Update AVS metadata URI for the DataHaven Service Manager") - .option("--chain ", "Target chain (hoodi, mainnet, anvil)") + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) .option("--uri ", "New metadata URI (required)") .option("--reset", "Use if you want to reset the metadata URI") .option("--rpc-url ", "Chain RPC URL (optional, defaults based on chain)") @@ -289,16 +360,26 @@ contractsCommand if (!chain) { throw new Error("--chain parameter is required"); } + let environment = options.environment; + if (!environment && command.parent) { + environment = command.parent.getOptionValue("environment"); + } await updateAVSMetadataURI(chain, options.uri, { execute: options.execute, - avsOwnerKey: options.avsOwnerKey + avsOwnerKey: options.avsOwnerKey, + environment }); }); -// Default Contracts command (runs check) +// Default Contracts command (runs check when no subcommand is specified) +// preAction hook on subcommands handles validation before the action runs contractsCommand .description("Show deployment plan, configuration, and status") - .option("--chain ", "Target chain (hoodi, mainnet, anvil)") + .option("--chain ", "Target chain (hoodi, ethereum, anvil)") + .option( + "--environment ", + "Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value." + ) .option("--rpc-url ", "Chain RPC URL (optional, defaults based on chain)") .option( "--private-key ", @@ -307,7 +388,9 @@ contractsCommand ) .option("--skip-verification", "Skip contract verification", false) .hook("preAction", contractsPreActionHook) - .action(contractsCheck); + .action(async (options: any, command: any) => { + await contractsCheck(options, command); + }); // ===== Exec ====== // Disabled until need arises diff --git a/test/configs/contracts/config.ts b/test/configs/contracts/config.ts index 58017e30..1c9971e5 100644 --- a/test/configs/contracts/config.ts +++ b/test/configs/contracts/config.ts @@ -14,8 +14,8 @@ export const CHAIN_CONFIGS = { EPOCHS_PER_SYNC_COMMITTEE_PERIOD: 256, SYNC_COMMITTEE_SIZE: 512 }, - mainnet: { - NETWORK_NAME: "mainnet", + ethereum: { + NETWORK_NAME: "ethereum", CHAIN_ID: 1, RPC_URL: "https://eth.llamarpc.com", BLOCK_EXPLORER: "https://etherscan.io/", @@ -39,22 +39,39 @@ export const getChainConfig = (chain: string) => { return CHAIN_CONFIGS[chain as keyof ChainConfigType]; }; -export const loadChainConfig = async (chain: string) => { +/** + * Builds the network identifier from chain and optional environment + * When environment is specified: {environment}-{chain} (e.g., "stagenet-hoodi") + * When environment is not specified: {chain} (e.g., "hoodi") + */ +export const buildNetworkId = (chain: string, environment?: string): string => { + return environment ? `${environment}-${chain}` : chain; +}; + +/** + * Loads chain configuration from the config file + * @param chain - The target chain (hoodi, mainnet, anvil) + * @param environment - Optional deployment environment (stagenet, testnet, mainnet) + * When specified, loads from {environment}-{chain}.json + */ +export const loadChainConfig = async (chain: string, environment?: string) => { + const networkId = buildNetworkId(chain, environment); + try { - const configPath = `../contracts/config/${chain}.json`; + const configPath = `../contracts/config/${networkId}.json`; const configFile = Bun.file(configPath); if (!(await configFile.exists())) { - throw new Error(`${chain} configuration file not found at ${configPath}`); + throw new Error(`${networkId} configuration file not found at ${configPath}`); } const configContent = await configFile.text(); const config = JSON.parse(configContent); - logger.debug(`✅ ${chain} configuration loaded successfully`); + logger.debug(`✅ ${networkId} configuration loaded successfully`); return config; } catch (error) { - logger.error(`❌ Failed to load ${chain} configuration: ${error}`); + logger.error(`❌ Failed to load ${networkId} configuration: ${error}`); throw error; } }; diff --git a/test/contract-bindings/generated.ts b/test/contract-bindings/generated.ts index e32728ce..aa580fd0 100644 --- a/test/contract-bindings/generated.ts +++ b/test/contract-bindings/generated.ts @@ -2047,6 +2047,13 @@ export const dataHavenServiceManagerAbi = [ outputs: [{ name: '', internalType: 'string', type: 'string' }], stateMutability: 'view', }, + { + type: 'function', + inputs: [], + name: 'MAX_ACTIVE_VALIDATORS', + outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }], + stateMutability: 'view', + }, { type: 'function', inputs: [], @@ -2058,9 +2065,17 @@ export const dataHavenServiceManagerAbi = [ type: 'function', inputs: [ { - name: '_strategies', - internalType: 'contract IStrategy[]', - type: 'address[]', + name: '_strategyMultipliers', + internalType: 'struct IRewardsCoordinatorTypes.StrategyAndMultiplier[]', + type: 'tuple[]', + components: [ + { + name: 'strategy', + internalType: 'contract IStrategy', + type: 'address', + }, + { name: 'multiplier', internalType: 'uint96', type: 'uint96' }, + ], }, ], name: 'addStrategiesToValidatorsSupportedStrategies', @@ -2076,8 +2091,8 @@ export const dataHavenServiceManagerAbi = [ }, { type: 'function', - inputs: [], - name: 'buildNewValidatorSetMessage', + inputs: [{ name: 'targetEra', internalType: 'uint64', type: 'uint64' }], + name: 'buildNewValidatorSetMessageForEra', outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }], stateMutability: 'view', }, @@ -2102,21 +2117,55 @@ export const dataHavenServiceManagerAbi = [ outputs: [], stateMutability: 'nonpayable', }, + { + type: 'function', + inputs: [], + name: 'getStrategiesAndMultipliers', + outputs: [ + { + name: '', + internalType: 'struct IRewardsCoordinatorTypes.StrategyAndMultiplier[]', + type: 'tuple[]', + components: [ + { + name: 'strategy', + internalType: 'contract IStrategy', + type: 'address', + }, + { name: 'multiplier', internalType: 'uint96', type: 'uint96' }, + ], + }, + ], + stateMutability: 'view', + }, { type: 'function', inputs: [ { name: 'initialOwner', internalType: 'address', type: 'address' }, { name: '_rewardsInitiator', internalType: 'address', type: 'address' }, { - name: 'validatorsStrategies', - internalType: 'contract IStrategy[]', - type: 'address[]', + name: 'validatorsStrategiesAndMultipliers', + internalType: 'struct IRewardsCoordinatorTypes.StrategyAndMultiplier[]', + type: 'tuple[]', + components: [ + { + name: 'strategy', + internalType: 'contract IStrategy', + type: 'address', + }, + { name: 'multiplier', internalType: 'uint96', type: 'uint96' }, + ], }, { name: '_snowbridgeGatewayAddress', internalType: 'address', type: 'address', }, + { + name: '_validatorSetSubmitter', + internalType: 'address', + type: 'address', + }, ], name: 'initialize', outputs: [], @@ -2178,10 +2227,11 @@ export const dataHavenServiceManagerAbi = [ { type: 'function', inputs: [ + { name: 'targetEra', internalType: 'uint64', type: 'uint64' }, { name: 'executionFee', internalType: 'uint128', type: 'uint128' }, { name: 'relayerFee', internalType: 'uint128', type: 'uint128' }, ], - name: 'sendNewValidatorSet', + name: 'sendNewValidatorSetForEra', outputs: [], stateMutability: 'payable', }, @@ -2207,6 +2257,36 @@ export const dataHavenServiceManagerAbi = [ outputs: [], stateMutability: 'nonpayable', }, + { + type: 'function', + inputs: [ + { + name: '_strategyMultipliers', + internalType: 'struct IRewardsCoordinatorTypes.StrategyAndMultiplier[]', + type: 'tuple[]', + components: [ + { + name: 'strategy', + internalType: 'contract IStrategy', + type: 'address', + }, + { name: 'multiplier', internalType: 'uint96', type: 'uint96' }, + ], + }, + ], + name: 'setStrategiesAndMultipliers', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'newSubmitter', internalType: 'address', type: 'address' }, + ], + name: 'setValidatorSetSubmitter', + outputs: [], + stateMutability: 'nonpayable', + }, { type: 'function', inputs: [ @@ -2237,6 +2317,13 @@ export const dataHavenServiceManagerAbi = [ outputs: [{ name: '', internalType: 'address', type: 'address' }], stateMutability: 'view', }, + { + type: 'function', + inputs: [{ name: '', internalType: 'contract IStrategy', type: 'address' }], + name: 'strategiesAndMultipliers', + outputs: [{ name: '', internalType: 'uint96', type: 'uint96' }], + stateMutability: 'view', + }, { type: 'function', inputs: [ @@ -2317,6 +2404,20 @@ export const dataHavenServiceManagerAbi = [ outputs: [{ name: '', internalType: 'address', type: 'address' }], stateMutability: 'view', }, + { + type: 'function', + inputs: [], + name: 'validatorSetSubmitter', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: '', internalType: 'address', type: 'address' }], + name: 'validatorSolochainAddressToEthAddress', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, { type: 'function', inputs: [{ name: '', internalType: 'address', type: 'address' }], @@ -2469,6 +2570,27 @@ export const dataHavenServiceManagerAbi = [ ], name: 'SolochainAddressUpdated', }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'strategyMultipliers', + internalType: 'struct IRewardsCoordinatorTypes.StrategyAndMultiplier[]', + type: 'tuple[]', + components: [ + { + name: 'strategy', + internalType: 'contract IStrategy', + type: 'address', + }, + { name: 'multiplier', internalType: 'uint96', type: 'uint96' }, + ], + indexed: false, + }, + ], + name: 'StrategiesAndMultipliersSet', + }, { type: 'event', anonymous: false, @@ -2495,15 +2617,64 @@ export const dataHavenServiceManagerAbi = [ ], name: 'ValidatorRemovedFromAllowlist', }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'targetEra', + internalType: 'uint64', + type: 'uint64', + indexed: true, + }, + { + name: 'payloadHash', + internalType: 'bytes32', + type: 'bytes32', + indexed: false, + }, + { + name: 'submitter', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'ValidatorSetMessageSubmitted', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'oldSubmitter', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'newSubmitter', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'ValidatorSetSubmitterUpdated', + }, { type: 'error', inputs: [], name: 'CallerIsNotValidator' }, { type: 'error', inputs: [], name: 'CantDeregisterFromMultipleOperatorSets' }, { type: 'error', inputs: [], name: 'CantRegisterToMultipleOperatorSets' }, + { type: 'error', inputs: [], name: 'EmptyValidatorSet' }, { type: 'error', inputs: [], name: 'IncorrectAVSAddress' }, { type: 'error', inputs: [], name: 'InvalidOperatorSetId' }, { type: 'error', inputs: [], name: 'InvalidSolochainAddressLength' }, { type: 'error', inputs: [], name: 'OnlyAllocationManager' }, { type: 'error', inputs: [], name: 'OnlyRewardsInitiator' }, + { type: 'error', inputs: [], name: 'OnlyValidatorSetSubmitter' }, { type: 'error', inputs: [], name: 'OperatorNotInAllowlist' }, + { type: 'error', inputs: [], name: 'SolochainAddressAlreadyAssigned' }, + { type: 'error', inputs: [], name: 'StrategyNotInOperatorSet' }, + { type: 'error', inputs: [], name: 'UnknownSolochainAddress' }, { type: 'error', inputs: [], name: 'ZeroAddress' }, ] as const @@ -10642,6 +10813,15 @@ export const readDataHavenServiceManagerDatahavenAvsMetadata = functionName: 'DATAHAVEN_AVS_METADATA', }) +/** + * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"MAX_ACTIVE_VALIDATORS"` + */ +export const readDataHavenServiceManagerMaxActiveValidators = + /*#__PURE__*/ createReadContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'MAX_ACTIVE_VALIDATORS', + }) + /** * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"VALIDATORS_SET_ID"` */ @@ -10652,12 +10832,21 @@ export const readDataHavenServiceManagerValidatorsSetId = }) /** - * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"buildNewValidatorSetMessage"` + * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"buildNewValidatorSetMessageForEra"` */ -export const readDataHavenServiceManagerBuildNewValidatorSetMessage = +export const readDataHavenServiceManagerBuildNewValidatorSetMessageForEra = /*#__PURE__*/ createReadContract({ abi: dataHavenServiceManagerAbi, - functionName: 'buildNewValidatorSetMessage', + functionName: 'buildNewValidatorSetMessageForEra', + }) + +/** + * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"getStrategiesAndMultipliers"` + */ +export const readDataHavenServiceManagerGetStrategiesAndMultipliers = + /*#__PURE__*/ createReadContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'getStrategiesAndMultipliers', }) /** @@ -10687,6 +10876,15 @@ export const readDataHavenServiceManagerSnowbridgeGateway = functionName: 'snowbridgeGateway', }) +/** + * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"strategiesAndMultipliers"` + */ +export const readDataHavenServiceManagerStrategiesAndMultipliers = + /*#__PURE__*/ createReadContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'strategiesAndMultipliers', + }) + /** * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"supportsAVS"` */ @@ -10705,6 +10903,24 @@ export const readDataHavenServiceManagerValidatorEthAddressToSolochainAddress = functionName: 'validatorEthAddressToSolochainAddress', }) +/** + * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"validatorSetSubmitter"` + */ +export const readDataHavenServiceManagerValidatorSetSubmitter = + /*#__PURE__*/ createReadContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'validatorSetSubmitter', + }) + +/** + * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"validatorSolochainAddressToEthAddress"` + */ +export const readDataHavenServiceManagerValidatorSolochainAddressToEthAddress = + /*#__PURE__*/ createReadContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'validatorSolochainAddressToEthAddress', + }) + /** * Wraps __{@link readContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"validatorsAllowlist"` */ @@ -10812,12 +11028,12 @@ export const writeDataHavenServiceManagerRenounceOwnership = }) /** - * Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"sendNewValidatorSet"` + * Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"sendNewValidatorSetForEra"` */ -export const writeDataHavenServiceManagerSendNewValidatorSet = +export const writeDataHavenServiceManagerSendNewValidatorSetForEra = /*#__PURE__*/ createWriteContract({ abi: dataHavenServiceManagerAbi, - functionName: 'sendNewValidatorSet', + functionName: 'sendNewValidatorSetForEra', }) /** @@ -10838,6 +11054,24 @@ export const writeDataHavenServiceManagerSetSnowbridgeGateway = functionName: 'setSnowbridgeGateway', }) +/** + * Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setStrategiesAndMultipliers"` + */ +export const writeDataHavenServiceManagerSetStrategiesAndMultipliers = + /*#__PURE__*/ createWriteContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'setStrategiesAndMultipliers', + }) + +/** + * Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setValidatorSetSubmitter"` + */ +export const writeDataHavenServiceManagerSetValidatorSetSubmitter = + /*#__PURE__*/ createWriteContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'setValidatorSetSubmitter', + }) + /** * Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"slashValidatorsOperator"` */ @@ -10971,12 +11205,12 @@ export const simulateDataHavenServiceManagerRenounceOwnership = }) /** - * Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"sendNewValidatorSet"` + * Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"sendNewValidatorSetForEra"` */ -export const simulateDataHavenServiceManagerSendNewValidatorSet = +export const simulateDataHavenServiceManagerSendNewValidatorSetForEra = /*#__PURE__*/ createSimulateContract({ abi: dataHavenServiceManagerAbi, - functionName: 'sendNewValidatorSet', + functionName: 'sendNewValidatorSetForEra', }) /** @@ -10997,6 +11231,24 @@ export const simulateDataHavenServiceManagerSetSnowbridgeGateway = functionName: 'setSnowbridgeGateway', }) +/** + * Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setStrategiesAndMultipliers"` + */ +export const simulateDataHavenServiceManagerSetStrategiesAndMultipliers = + /*#__PURE__*/ createSimulateContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'setStrategiesAndMultipliers', + }) + +/** + * Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setValidatorSetSubmitter"` + */ +export const simulateDataHavenServiceManagerSetValidatorSetSubmitter = + /*#__PURE__*/ createSimulateContract({ + abi: dataHavenServiceManagerAbi, + functionName: 'setValidatorSetSubmitter', + }) + /** * Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"slashValidatorsOperator"` */ @@ -11129,6 +11381,15 @@ export const watchDataHavenServiceManagerSolochainAddressUpdatedEvent = eventName: 'SolochainAddressUpdated', }) +/** + * Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"StrategiesAndMultipliersSet"` + */ +export const watchDataHavenServiceManagerStrategiesAndMultipliersSetEvent = + /*#__PURE__*/ createWatchContractEvent({ + abi: dataHavenServiceManagerAbi, + eventName: 'StrategiesAndMultipliersSet', + }) + /** * Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"ValidatorAddedToAllowlist"` */ @@ -11147,6 +11408,24 @@ export const watchDataHavenServiceManagerValidatorRemovedFromAllowlistEvent = eventName: 'ValidatorRemovedFromAllowlist', }) +/** + * Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"ValidatorSetMessageSubmitted"` + */ +export const watchDataHavenServiceManagerValidatorSetMessageSubmittedEvent = + /*#__PURE__*/ createWatchContractEvent({ + abi: dataHavenServiceManagerAbi, + eventName: 'ValidatorSetMessageSubmitted', + }) + +/** + * Wraps __{@link watchContractEvent}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `eventName` set to `"ValidatorSetSubmitterUpdated"` + */ +export const watchDataHavenServiceManagerValidatorSetSubmitterUpdatedEvent = + /*#__PURE__*/ createWatchContractEvent({ + abi: dataHavenServiceManagerAbi, + eventName: 'ValidatorSetSubmitterUpdated', + }) + /** * Wraps __{@link readContract}__ with `abi` set to __{@link delegationManagerAbi}__ */ diff --git a/test/e2e/framework/validators.ts b/test/e2e/framework/validators.ts index 4dcd074c..2ecee8a9 100644 --- a/test/e2e/framework/validators.ts +++ b/test/e2e/framework/validators.ts @@ -7,11 +7,13 @@ import { $ } from "bun"; import { allocationManagerAbi, dataHavenServiceManagerAbi, - delegationManagerAbi + delegationManagerAbi, + strategyManagerAbi } from "contract-bindings"; import { type Deployments, logger, waitForContainerToStart } from "utils"; import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants"; import { getPublicPort } from "utils/docker"; +import { erc20Abi } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import validatorSet from "../../configs/validator-set.json"; import type { LaunchedNetwork } from "../../launcher/types/launchedNetwork"; @@ -120,9 +122,50 @@ export async function registerOperator( const { connectors, deployments } = options; const validator = getValidator(validatorName); const account = privateKeyToAccount(validator.privateKey as `0x${string}`); + const { publicClient, walletClient } = connectors; + + // Deposit tokens into deployed strategies + const deployedStrategies = deployments.DeployedStrategies ?? []; + for (const strategy of deployedStrategies) { + const balance = await publicClient.readContract({ + address: strategy.underlyingToken as `0x${string}`, + abi: erc20Abi, + functionName: "balanceOf", + args: [account.address] + }); + + if (balance > 0n) { + const depositAmount = balance / 10n; + + const approveHash = await walletClient.writeContract({ + address: strategy.underlyingToken as `0x${string}`, + abi: erc20Abi, + functionName: "approve", + args: [deployments.StrategyManager, depositAmount], + account, + chain: null + }); + await publicClient.waitForTransactionReceipt({ hash: approveHash }); + + const depositHash = await walletClient.writeContract({ + address: deployments.StrategyManager, + abi: strategyManagerAbi, + functionName: "depositIntoStrategy", + args: [ + strategy.address as `0x${string}`, + strategy.underlyingToken as `0x${string}`, + depositAmount + ], + account, + chain: null + }); + await publicClient.waitForTransactionReceipt({ hash: depositHash }); + logger.debug(`Deposited ${depositAmount} tokens into strategy ${strategy.address}`); + } + } // Register as EigenLayer operator - const operatorHash = await connectors.walletClient.writeContract({ + const operatorHash = await walletClient.writeContract({ address: deployments.DelegationManager as `0x${string}`, abi: delegationManagerAbi, functionName: "registerAsOperator", @@ -131,7 +174,7 @@ export async function registerOperator( chain: null }); - const operatorReceipt = await connectors.publicClient.waitForTransactionReceipt({ + const operatorReceipt = await publicClient.waitForTransactionReceipt({ hash: operatorHash }); if (operatorReceipt.status !== "success") { @@ -139,7 +182,7 @@ export async function registerOperator( } // Register for operator sets - const hash = await connectors.walletClient.writeContract({ + const registerHash = await walletClient.writeContract({ address: deployments.AllocationManager as `0x${string}`, abi: allocationManagerAbi, functionName: "registerForOperatorSets", @@ -155,10 +198,40 @@ export async function registerOperator( chain: null }); - const receipt = await connectors.publicClient.waitForTransactionReceipt({ hash }); - if (receipt.status !== "success") { - throw new Error(`Operator set registration failed: ${receipt.status}`); + const registerReceipt = await publicClient.waitForTransactionReceipt({ hash: registerHash }); + if (registerReceipt.status !== "success") { + throw new Error(`Operator set registration failed: ${registerReceipt.status}`); } - logger.debug(`Registered ${validatorName} as operator (gas: ${receipt.gasUsed})`); + // Allocate full magnitude to the validator operator set + const strategyAddresses = deployedStrategies.map((s) => s.address as `0x${string}`); + const newMagnitudes = strategyAddresses.map(() => BigInt(1e18)); + + const allocateHash = await walletClient.writeContract({ + address: deployments.AllocationManager as `0x${string}`, + abi: allocationManagerAbi, + functionName: "modifyAllocations", + args: [ + account.address, + [ + { + operatorSet: { + avs: deployments.ServiceManager as `0x${string}`, + id: 0 + }, + strategies: strategyAddresses, + newMagnitudes + } + ] + ], + account, + chain: null + }); + + const allocateReceipt = await publicClient.waitForTransactionReceipt({ hash: allocateHash }); + if (allocateReceipt.status !== "success") { + throw new Error(`Magnitude allocation failed: ${allocateReceipt.status}`); + } + + logger.debug(`Registered ${validatorName} as operator (gas: ${registerReceipt.gasUsed})`); } diff --git a/test/e2e/suites/validator-set-update.test.ts b/test/e2e/suites/validator-set-update.test.ts index 7e324e79..fe18b4cb 100644 --- a/test/e2e/suites/validator-set-update.test.ts +++ b/test/e2e/suites/validator-set-update.test.ts @@ -5,7 +5,8 @@ * - Start network and ensure 4 validator nodes are running (Alice, Bob, Charlie, Dave). * - Confirm initial mapping exists only for Alice/Bob on `ServiceManager`. * - Allowlist and register Charlie/Dave as operators on Ethereum. - * - Send updated validator set via `ServiceManager.sendNewValidatorSet`, assert Gateway `OutboundMessageAccepted`. + * - Send updated validator set via `ServiceManager.sendNewValidatorSetForEra`, + * assert Gateway `OutboundMessageAccepted`. * - Observe `ExternalValidators.ExternalValidatorsSet` on DataHaven (substrate), confirming propagation. */ import { beforeAll, describe, expect, it } from "bun:test"; @@ -13,6 +14,7 @@ import { getOwnerAccount } from "launcher/validators"; import { CROSS_CHAIN_TIMEOUTS, type Deployments, + getPapiSigner, logger, parseDeploymentsFile, ZERO_ADDRESS @@ -67,6 +69,20 @@ describe("Validator Set Update", () => { beforeAll(async () => { deployments = await parseDeploymentsFile(); connectors = suite.getTestConnectors(); + + // Pause era rotation early so the active era stabilizes during tests 1-3 (~28s), + // avoiding the ~80s wait inside the cross-chain test. + // Tests 1-3 only touch Ethereum contracts and don't depend on era rotation. + const { dhApi } = connectors; + const pauseTx = dhApi.tx.Sudo.sudo({ + call: dhApi.tx.ExternalValidators.force_era({ + mode: { type: "ForceNone", value: undefined } + }).decodedCall + }); + const pauseResult = await pauseTx.signAndSubmit(getPapiSigner("ALITH")); + if (!pauseResult.ok) { + throw new Error("Failed to pause era rotation"); + } }); it("should verify test environment", async () => { @@ -159,25 +175,49 @@ describe("Validator Set Update", () => { async () => { const { publicClient, walletClient, dhApi } = connectors; + // Era rotation was paused in beforeAll. Wait for any pending transition to settle + // (ForceNone prevents new eras, but an in-progress one must finish first). + let stableEraIndex: number; + // eslint-disable-next-line no-constant-condition + while (true) { + const activeEra = (await dhApi.query.ExternalValidators.ActiveEra.getValue())?.index ?? 0; + const currentEra = (await dhApi.query.ExternalValidators.CurrentEra.getValue()) ?? 0; + if (currentEra === activeEra) { + stableEraIndex = activeEra; + break; + } + await new Promise((r) => setTimeout(r, 6_000)); // ~1 substrate block + } + + const targetEra = BigInt(stableEraIndex + 1); + // Send the updated validator set via Snowbridge const hash = await walletClient.writeContract({ address: deployments.ServiceManager as `0x${string}`, abi: dataHavenServiceManagerAbi, - functionName: "sendNewValidatorSet", - args: [parseEther("0.1"), parseEther("0.2")], + functionName: "sendNewValidatorSetForEra", + args: [targetEra, parseEther("0.1"), parseEther("0.2")], value: parseEther("0.3"), - gas: 1000000n, account: getOwnerAccount(), chain: null }); - const receipt = await publicClient.waitForTransactionReceipt({ hash }); + logger.info( + `sendNewValidatorSet tx status: ${receipt.status}, block: ${receipt.blockNumber}` + ); expect(receipt.status).toBe("success"); // Verify OutboundMessageAccepted event was emitted const hasOutboundAccepted = (receipt.logs ?? []).some((log: any) => { try { - const decoded = decodeEventLog({ abi: gatewayAbi, data: log.data, topics: log.topics }); + const decoded = decodeEventLog({ + abi: gatewayAbi, + data: log.data, + topics: log.topics + }); + if (decoded.eventName === "OutboundMessageAccepted") { + logger.info(`OutboundMessageAccepted event: nonce=${(decoded.args as any)?.nonce}`); + } return decoded.eventName === "OutboundMessageAccepted"; } catch { return false; @@ -185,14 +225,25 @@ describe("Validator Set Update", () => { }); expect(hasOutboundAccepted).toBe(true); + logger.info("Waiting for ExternalValidators.ExternalValidatorsSet event on DataHaven..."); // Wait for the validator set to be updated on Substrate await waitForDataHavenEvent({ api: dhApi, pallet: "ExternalValidators", event: "ExternalValidatorsSet", + filter: (event: { external_index: number | bigint }) => + BigInt(event.external_index) === targetEra, timeout: CROSS_CHAIN_TIMEOUTS.ETH_TO_DH_MS }); + // Resume era rotation + const resumeTx = dhApi.tx.Sudo.sudo({ + call: dhApi.tx.ExternalValidators.force_era({ + mode: { type: "NotForcing", value: undefined } + }).decodedCall + }); + await resumeTx.signAndSubmit(getPapiSigner("ALITH")); + // Verify new validators are in storage const validators = await dhApi.query.ExternalValidators.ExternalValidators.getValue(); const expectedAddresses = newValidators.map((v) => v.solochainAddress.toLowerCase()); diff --git a/test/launcher/relayers.ts b/test/launcher/relayers.ts index 27fca347..a64cbad4 100644 --- a/test/launcher/relayers.ts +++ b/test/launcher/relayers.ts @@ -441,8 +441,8 @@ export const launchRelayers = async ( await $`mkdir -p ${RELAYER_CONFIG_DIR}`.quiet(); const datastorePath = "tmp/datastore"; - logger.debug(`Ensuring datastore directory exists: ${datastorePath}`); - await $`mkdir -p ${datastorePath}`.quiet(); + logger.debug(`Clearing and recreating datastore directory: ${datastorePath}`); + await $`rm -rf ${datastorePath} && mkdir -p ${datastorePath}`.quiet(); const ethWsPort = await getPortFromKurtosis("el-1-reth-lodestar", "ws", kurtosisEnclaveName); const ethHttpPort = await getPortFromKurtosis("cl-1-lodestar-reth", "http", kurtosisEnclaveName); diff --git a/test/launcher/storagehub-docker.ts b/test/launcher/storagehub-docker.ts index c1de22a9..a9f64c0e 100644 --- a/test/launcher/storagehub-docker.ts +++ b/test/launcher/storagehub-docker.ts @@ -1,11 +1,15 @@ import { $ } from "bun"; import { getPublicPort, killExistingContainers, logger, waitForContainerToStart } from "utils"; -import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants"; +import { DEFAULT_SUBSTRATE_WS_PORT, SUBSTRATE_FUNDED_ACCOUNTS } from "utils/constants"; import { waitFor } from "utils/waits"; import type { DataHavenOptions } from "./datahaven"; import { isNetworkReady } from "./datahaven"; import type { LaunchedNetwork } from "./types/launchedNetwork"; +/** + * Important ! This is for local deployment only. We are using mDNS discovery when startinn node with the `--discover-local` flag + */ + /** * PostgreSQL configuration for StorageHub Indexer and Fisherman */ @@ -109,48 +113,25 @@ export const getPostgresUrl = (networkId: string): string => { * Injects a BCSV ECDSA key into a StorageHub provider node's keystore. * * @param containerName - Name of the Docker container - * @param seed - The seed phrase for key generation - * @param derivation - Key derivation path (e.g., "//Charlie") + * @param secretKey - The secret key (or private key) we want to add to the node */ export const injectStorageHubKey = async ( containerName: string, - seed: string, - derivation: string + secretKey: string ): Promise => { - logger.info(`🔑 Injecting key ${derivation} into ${containerName}...`); - - const suri = `${seed}${derivation}`; + logger.info(`🔑 Injecting key into ${containerName}...`); // Use Bun's $ directly with docker exec (no sh -c wrapper needed) // This properly handles the spaces in the seed phrase try { - await $`docker exec ${containerName} datahaven-node key insert --base-path /data --chain dev --key-type bcsv --scheme ecdsa --suri ${suri}`.nothrow(); - logger.success(`Key ${derivation} injected successfully`); + await $`docker exec ${containerName} datahaven-node key insert --base-path /data --key-type bcsv --scheme ecdsa --suri ${secretKey}`; + logger.success("Key injected successfully"); } catch (error) { - logger.error(`Failed to inject key ${derivation}: ${error}`); + logger.error(`Failed to inject key : ${error}`); throw error; } }; -/** - * Gets the bootnode address from a running validator node. - * - * For local development with Docker, nodes on the same network can discover each other - * via mDNS (--discover-local flag), so explicit bootnodes are optional. - * - * To use explicit bootnodes, we'd need to extract the peer ID from the validator node, - * which requires querying the RPC endpoint. For simplicity in local dev, we skip this. - * - * @param containerName - Name of the validator container (e.g., datahaven-alice-cli-launch) - * @returns Multiaddress string for bootnode, or empty string to skip bootnodes - */ -export const getBootnodeAddress = async (containerName: string): Promise => { - // For local Docker development, nodes discover each other via mDNS - // No explicit bootnode needed with --discover-local flag - logger.debug(`Skipping explicit bootnode for ${containerName} - using mDNS discovery`); - return ""; -}; - /** * Launches a StorageHub MSP (Main Storage Provider) node. * @@ -166,10 +147,6 @@ export const launchMspNode = async ( const containerName = `storagehub-msp-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9945; // External port for MSP node - const aliceContainer = `datahaven-alice-${options.networkId}`; - - // Get bootnode address (empty for local dev with mDNS discovery) - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const command: string[] = [ "docker", @@ -182,10 +159,10 @@ export const launchMspNode = async ( "-p", `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, - "--chain", - "dev", "--name", "msp-charlie", + "--chain", + "local", "--rpc-port", `${DEFAULT_SUBSTRATE_WS_PORT}`, "--rpc-external", @@ -208,19 +185,13 @@ export const launchMspNode = async ( "1073741824" // 1 GiB ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); await waitForContainerToStart(containerName); // Inject key - const seed = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; - await injectStorageHubKey(containerName, seed, "//Charlie"); + await injectStorageHubKey(containerName, SUBSTRATE_FUNDED_ACCOUNTS.CHARLETH.privateKey); // Restart container to load key logger.info("🔄 Restarting MSP node to load key..."); @@ -263,10 +234,6 @@ export const launchBspNode = async ( const containerName = `storagehub-bsp-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9946; // External port for BSP node - const aliceContainer = `datahaven-alice-${options.networkId}`; - - // Get bootnode address (empty for local dev with mDNS discovery) - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const command: string[] = [ "docker", @@ -279,10 +246,10 @@ export const launchBspNode = async ( "-p", `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, - "--chain", - "dev", "--name", - "bsp-dave", + "bsp-dorothy", + "--chain", + "local", "--rpc-port", `${DEFAULT_SUBSTRATE_WS_PORT}`, "--rpc-external", @@ -303,19 +270,13 @@ export const launchBspNode = async ( "1073741824" // 1 GiB ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); await waitForContainerToStart(containerName); - // Inject key (using Dave instead of Eve for BSP) - const seed = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; - await injectStorageHubKey(containerName, seed, "//Dave"); + // Inject key + await injectStorageHubKey(containerName, SUBSTRATE_FUNDED_ACCOUNTS.DOROTHY.privateKey); // Restart container to load key logger.info("🔄 Restarting BSP node to load key..."); @@ -358,10 +319,7 @@ export const launchIndexerNode = async ( const containerName = `storagehub-indexer-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9947; // External port for Indexer node - const aliceContainer = `datahaven-alice-${options.networkId}`; - // Get bootnode address (empty for local dev with mDNS discovery) and PostgreSQL URL - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const postgresUrl = getPostgresUrl(options.networkId); const command: string[] = [ @@ -375,10 +333,10 @@ export const launchIndexerNode = async ( "-p", `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, - "--chain", - "dev", "--name", "indexer", + "--chain", + "local", "--rpc-port", `${DEFAULT_SUBSTRATE_WS_PORT}`, "--rpc-external", @@ -395,11 +353,6 @@ export const launchIndexerNode = async ( postgresUrl ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); @@ -441,10 +394,7 @@ export const launchFishermanNode = async ( const containerName = `storagehub-fisherman-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9948; // External port for Fisherman node - const aliceContainer = `datahaven-alice-${options.networkId}`; - // Get bootnode address (empty for local dev with mDNS discovery) and PostgreSQL URL - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const postgresUrl = getPostgresUrl(options.networkId); const command: string[] = [ @@ -459,7 +409,7 @@ export const launchFishermanNode = async ( `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, "--chain", - "dev", + "local", "--name", "fisherman", "--rpc-port", @@ -476,11 +426,6 @@ export const launchFishermanNode = async ( postgresUrl ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); @@ -507,6 +452,63 @@ export const launchFishermanNode = async ( logger.success(`Fisherman node started on port ${wsPort}`); }; +/** + * Launches a StorageHub Backend container. + * + * @param options - Configuration options for launching the network + * @param launchedNetwork - The launched network instance to track the node + */ +export const launchBackend = async ( + options: DataHavenOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + logger.info("🚀 Launching StorageHub Backend..."); + + const backendImage = "moonsonglabs/storage-hub-msp-backend:latest"; + const containerName = `storagehub-backend-${options.networkId}`; + const dockerNetworkName = `datahaven-${options.networkId}`; + const containerNameMSP = `storagehub-msp-${options.networkId}`; + const postgresUrl = getPostgresUrl(options.networkId); + const apiPort = 8080; + + const command: string[] = [ + "docker", + "run", + "-d", + "--name", + containerName, + "--network", + dockerNetworkName, + "-p", + `${apiPort}:8080`, + "-e", + "RUST_LOG=info", + backendImage, + "--chain", + "local", + "--log-format", + "text", + "--database-url", + postgresUrl, + "--rpc-url", + `ws://${containerNameMSP}:${DEFAULT_SUBSTRATE_WS_PORT}`, + "--msp-callback-url", + `http://${containerName}:8080`, + "--msp-trusted-file-transfer-server-url", + `http://${containerNameMSP}:7070` + ]; + + logger.debug(`Executing: ${command.join(" ")}`); + await $`sh -c "${command.join(" ")}"`.nothrow(); + + await waitForContainerToStart(containerName); + + // Register in launched network + launchedNetwork.addContainer(containerName, { http: apiPort }, { http: apiPort }); + + logger.success(`StorageHub Backend container started on port ${apiPort}`); +}; + /** * Stops and removes all StorageHub containers. * diff --git a/test/moonwall/contracts/src/ECContracts.sol b/test/moonwall/contracts/src/ECContracts.sol new file mode 100644 index 00000000..2faab0db --- /dev/null +++ b/test/moonwall/contracts/src/ECContracts.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.3; + +contract RecoveryChecker { + constructor() {} + + function checkRecovery( + bytes32 msgHash, + uint256 v, + bytes32 r, + bytes32 s + ) public view returns (address) { + (, bytes memory data) = address(0x01).staticcall( + abi.encode(msgHash, v, r, s) + ); + return abi.decode(data, (address)); + } +} + +contract PairingChecker { + bool public status = false; + + function callBn256Pairing(bytes memory input) + public + returns (bytes32 result) + { + uint256 len = input.length; + assembly { + let memPtr := mload(0x40) + let success := call( + gas(), + 0x08, + 0, + add(input, 0x20), + len, + memPtr, + 0x20 + ) + switch success + case 0 { + revert(0, 0) + } + default { + result := mload(memPtr) + } + } + status = + result == + 0x0000000000000000000000000000000000000000000000000000000000000001; + } +} diff --git a/test/moonwall/contracts/src/FailingConstructor.sol b/test/moonwall/contracts/src/FailingConstructor.sol new file mode 100644 index 00000000..a30781c9 --- /dev/null +++ b/test/moonwall/contracts/src/FailingConstructor.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity >=0.8.3; + +contract FailingConstructor { + constructor() { + require(false); + } +} diff --git a/test/moonwall/contracts/src/HasherChecker.sol b/test/moonwall/contracts/src/HasherChecker.sol new file mode 100644 index 00000000..b49eed63 --- /dev/null +++ b/test/moonwall/contracts/src/HasherChecker.sol @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity >=0.8.3; + +contract HasherChecker { + uint256 public lastResult; + + function ripemd160Check() public pure { + require( + ripemd160(bytes("Hello World!")) == + hex"8476ee4631b9b30ac2754b0ee0c47e161d3f724c" + ); + } + + function bn128AdditionCheck() public { + bool success; + uint256[4] memory input = [ + 0x2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703, + 0x301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915, + 0x18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9, + 0x063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266 + ]; + uint256[2] memory result; + + assembly { + // 0x06 id of the bn256Add precompile + // 0 number of ether to transfer + // 128 size of call parameters, i.e. 128 bytes total + // 64 size of return value, i.e. 64 bytes / 512 bit for a BN256 curve point + success := call(not(0), 0x06, 0, input, 128, result, 64) + } + require(success, "elliptic curve addition failed"); + require( + result[0] == + 0x2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb7, + "failed" + ); + require( + result[1] == + 0x21611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204, + "failed" + ); + } + + function bn128MultiplyCheck() public { + bool success; + uint256[3] memory input = [ + 0x1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3, + 0x1a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6, + 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000 + ]; + uint256[2] memory result; + + assembly { + // 0x07 id of the bn256Mul precompile + // 0 number of ether to transfer + // 96 size of call parameters, i.e. 128 bytes total + // 64 size of return value, i.e. 64 bytes / 512 bit for a BN256 curve point + success := call(not(0), 0x07, 0, input, 96, result, 64) + } + require(success, "elliptic curve addition failed"); + require( + result[0] == + 0x1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3, + "failed" + ); + require( + result[1] == + 0x163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451, + "failed" + ); + } + + function bn128PairingCheck() public { + uint256[12] memory input = [ + 0x2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02, + 0x03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84, + 0x1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee, + 0x2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f, + 0x21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237, + 0x096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f, + 0x06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db9, + 0x22160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1, + 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2, + 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed, + 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b, + 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa + ]; + uint256[1] memory result; + bool success; + assembly { + // 0x08 id of the bn256CheckPairing precompile + // 0 number of ether to transfer + // 0 since we have an array of fixed length, our input starts in 0 + // 384 size of call parameters, i.e. 12*256 bits == 384 bytes + // 32 size of result (one 32 byte boolean!) + success := call(sub(gas(), 2000), 0x08, 0, input, 384, result, 32) + } + require(success, "elliptic curve pairing failed"); + require(result[0] == 1, "failed"); + } + + function modExpWrapper( + uint256 _b, + uint256 _e, + uint256 _m + ) public returns (uint256 result) { + assembly { + // Free memory pointer + let pointer := mload(0x40) + // Define length of base, exponent and modulus. 0x20 == 32 bytes + mstore(pointer, 0x20) + mstore(add(pointer, 0x20), 0x20) + mstore(add(pointer, 0x40), 0x20) + // Define variables base, exponent and modulus + mstore(add(pointer, 0x60), _b) + mstore(add(pointer, 0x80), _e) + + mstore(add(pointer, 0xa0), _m) + // Store the result + let value := mload(0xc0) + // Call the precompiled contract 0x05 = bigModExp + if iszero(call(not(0), 0x05, 0, pointer, 0xc0, value, 0x20)) { + revert(0, 0) + } + result := mload(value) + } + } + + function modExpVerify( + uint256 _base, + uint256 _exponent, + uint256 _modulus + ) public { + lastResult = modExpWrapper(_base, _exponent, _modulus); + } + + function getResult() public view returns (uint256) { + return lastResult; + } + + function modExpChecker() public { + require(modExpWrapper(3, 5, 7) == 5); + require(modExpWrapper(5, 7, 11) == 3); + } + + function blake2Wrapper( + uint32 rounds, + bytes32[2] memory h, + bytes32[4] memory m, + bytes8[2] memory t, + bool f + ) public view returns (bytes32[2] memory) { + bytes32[2] memory output; + + bytes memory args = abi.encodePacked( + rounds, + h[0], + h[1], + m[0], + m[1], + m[2], + m[3], + t[0], + t[1], + f + ); + + assembly { + if iszero( + staticcall(not(0), 0x09, add(args, 32), 0xd5, output, 0x40) + ) { + revert(0, 0) + } + } + + return output; + } + + function blake2Check() public { + uint32 rounds = 12; + + bytes32[2] memory h; + h[ + 0 + ] = hex"48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5"; + h[ + 1 + ] = hex"d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b"; + + bytes32[4] memory m; + m[ + 0 + ] = hex"6162630000000000000000000000000000000000000000000000000000000000"; + m[ + 1 + ] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + m[ + 2 + ] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + m[ + 3 + ] = hex"0000000000000000000000000000000000000000000000000000000000000000"; + + bytes8[2] memory t; + t[0] = hex"03000000"; + t[1] = hex"00000000"; + + bool f = true; + + // Expected output: + // ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1 + // 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923 + + bytes32[2] memory result = blake2Wrapper(rounds, h, m, t, f); + require( + result[0] == + 0xba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1, + "failed" + ); + require( + result[1] == + 0x7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923, + "failed" + ); + } +} diff --git a/test/moonwall/contracts/src/StorageLoop.sol b/test/moonwall/contracts/src/StorageLoop.sol new file mode 100644 index 00000000..fcab6859 --- /dev/null +++ b/test/moonwall/contracts/src/StorageLoop.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.2 <0.9.0; + +contract StorageLoop { + mapping(uint256 => uint256) public map; + mapping(uint256 => uint256) public map2; + + function store(uint16 n) public { + for (uint16 i = 0; i < n; i++) { + map[i] = i + 1; + } + } + + function store2(uint256 i) public { + map2[i] = i; + } +} diff --git a/test/moonwall/helpers/constants.ts b/test/moonwall/helpers/constants.ts index 8b3123c2..d241ca69 100644 --- a/test/moonwall/helpers/constants.ts +++ b/test/moonwall/helpers/constants.ts @@ -4,11 +4,14 @@ */ import type { GenericContext } from "@moonwall/cli"; -import { - ALITH_GENESIS_FREE_BALANCE, - ALITH_GENESIS_LOCK_BALANCE, - ALITH_GENESIS_RESERVE_BALANCE -} from "@moonwall/util"; + +// DataHaven genesis balance constants +// From operator/runtime/stagenet/src/genesis_config_presets.rs: +// Each endowed account receives: 1u128 << 80 +// No locks or reserves are set at genesis +export const ALITH_GENESIS_FREE_BALANCE = 1n << 80n; // 1208925819614629174706176n +export const ALITH_GENESIS_LOCK_BALANCE = 0n; +export const ALITH_GENESIS_RESERVE_BALANCE = 0n; export const ALITH_GENESIS_TRANSFERABLE_COUNT = ALITH_GENESIS_FREE_BALANCE + ALITH_GENESIS_RESERVE_BALANCE - ALITH_GENESIS_LOCK_BALANCE; @@ -35,6 +38,27 @@ class RuntimeConstant { } } +// Currency units for DataHaven stagenet +// These match the runtime configuration in operator/runtime/stagenet/src/lib.rs +export const HAVE = 1_000_000_000_000_000_000n; // 10^18 +export const MICROHAVE = 1_000_000_000_000n; // 10^12 +export const SUPPLY_FACTOR = 1n; +export const STORAGE_BYTE_FEE = 100n * MICROHAVE * SUPPLY_FACTOR; // 100_000_000_000_000n + +/** + * Calculate deposit cost matching the runtime's deposit() function + * deposit(items, bytes) = items * HAVE * SUPPLY_FACTOR + bytes * STORAGE_BYTE_FEE + */ +export function deposit(items: number, bytes: number): bigint { + return BigInt(items) * HAVE * SUPPLY_FACTOR + BigInt(bytes) * STORAGE_BYTE_FEE; +} + +// Identity pallet deposit constants (stagenet) +// Calculated from: operator/runtime/stagenet/src/configs/mod.rs +export const IDENTITY_BASIC_DEPOSIT = deposit(1, 258); // 1_025_800_000_000_000_000n +export const IDENTITY_BYTE_DEPOSIT = deposit(0, 1); // 100_000_000_000_000n +export const IDENTITY_SUB_ACCOUNT_DEPOSIT = deposit(1, 53); // 1_005_300_000_000_000_000n + const DATAHAVEN_CONSTANTS = { BLOCK_WEIGHT_LIMIT: new RuntimeConstant({ 0: 2_000_000_000_000n @@ -57,7 +81,8 @@ const DATAHAVEN_CONSTANTS = { CALL_PERMIT: "0x000000000000000000000000000000000000080a" as const, PROXY: "0x000000000000000000000000000000000000080b" as const, ERC20_BALANCES: "0x0000000000000000000000000000000000000802" as const, - PRECOMPILE_REGISTRY: "0x0000000000000000000000000000000000000815" as const + PRECOMPILE_REGISTRY: "0x0000000000000000000000000000000000000815" as const, + IDENTITY: "0x0000000000000000000000000000000000000818" as const } } as const; diff --git a/test/moonwall/helpers/index.ts b/test/moonwall/helpers/index.ts index 76578e1e..ea1dffea 100644 --- a/test/moonwall/helpers/index.ts +++ b/test/moonwall/helpers/index.ts @@ -8,6 +8,7 @@ export * from "./block"; export * from "./constants"; +export { PRECOMPILE_IDENTITY_ADDRESS, PRECOMPILE_PROXY_ADDRESS } from "./precompile-addresses"; export * from "./contracts"; // Export unique functions from eth-transactions that aren't in evm.ts export { extractRevertReason } from "./eth-transactions"; @@ -16,3 +17,5 @@ export * from "./expect"; export * from "./fees"; export * from "./parameters"; export * from "./transactions"; +export * from "./modexp"; +export * from "./precompile-contract-calls"; diff --git a/test/moonwall/helpers/modexp.ts b/test/moonwall/helpers/modexp.ts new file mode 100644 index 00000000..1842468b --- /dev/null +++ b/test/moonwall/helpers/modexp.ts @@ -0,0 +1,97 @@ +/** + * Test vectors for modular exponentiation precompile tests + * Adapted from Moonbeam test helpers + */ + +export const testVectors = { + "nagydani-1-square": { + base: "e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5", + exponent: "02", + modulus: + "fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", + }, + "nagydani-1-qube": { + base: "e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5", + exponent: "03", + modulus: + "fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", + }, + "nagydani-1-pow0x10001": { + base: "e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5", + exponent: "010001", + modulus: + "fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", + }, + "nagydani-2-square": { + base: "cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51", + exponent: "02", + modulus: + "e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + }, + "nagydani-2-qube": { + base: "cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51", + exponent: "03", + modulus: + "e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + }, + "nagydani-2-pow0x10001": { + base: "cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51", + exponent: "010001", + modulus: + "e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + }, + "nagydani-3-square": { + base: "c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb", + exponent: "02", + modulus: + "d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + }, + "nagydani-3-qube": { + base: "c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb", + exponent: "03", + modulus: + "d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + }, + "nagydani-3-pow0x10001": { + base: "c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb", + exponent: "010001", + modulus: + "d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + }, + "nagydani-4-square": { + base: "db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81", + exponent: "02", + modulus: + "df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + }, + "nagydani-4-qube": { + base: "db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81", + exponent: "03", + modulus: + "df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + }, + "nagydani-4-pow0x10001": { + base: "db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81", + exponent: "010001", + modulus: + "df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + }, + "nagydani-5-square": { + base: "c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf", + exponent: "02", + modulus: + "e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + }, + "nagydani-5-qube": { + base: "c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf", + exponent: "03", + modulus: + "e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + }, + "nagydani-5-pow0x10001": { + base: "c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf", + exponent: "010001", + modulus: + "e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + }, +} as const; diff --git a/test/moonwall/helpers/precompile-addresses.ts b/test/moonwall/helpers/precompile-addresses.ts new file mode 100644 index 00000000..4eac619b --- /dev/null +++ b/test/moonwall/helpers/precompile-addresses.ts @@ -0,0 +1,17 @@ +/** + * Precompile addresses for DataHaven + * These addresses match Moonbeam's precompile address scheme + */ + +export const PRECOMPILE_NATIVE_ERC20_ADDRESS = "0x0000000000000000000000000000000000000802" as const; +export const PRECOMPILE_ERC20_BALANCES_ADDRESS = PRECOMPILE_NATIVE_ERC20_ADDRESS; // Alias +export const PRECOMPILE_BATCH_ADDRESS = "0x0000000000000000000000000000000000000808" as const; +export const PRECOMPILE_CALL_PERMIT_ADDRESS = "0x000000000000000000000000000000000000080a" as const; +export const PRECOMPILE_PROXY_ADDRESS = "0x000000000000000000000000000000000000080b" as const; +export const PRECOMPILE_TREASURY_COUNCIL_ADDRESS = "0x0000000000000000000000000000000000000810" as const; +export const PRECOMPILE_REFERENDA_ADDRESS = "0x0000000000000000000000000000000000000811" as const; +export const PRECOMPILE_CONVICTION_VOTING_ADDRESS = "0x0000000000000000000000000000000000000812" as const; +export const PRECOMPILE_PREIMAGE_ADDRESS = "0x0000000000000000000000000000000000000813" as const; +export const PRECOMPILE_TECHNICAL_COMMITTEE_ADDRESS = "0x0000000000000000000000000000000000000814" as const; +export const PRECOMPILE_REGISTRY_ADDRESS = "0x0000000000000000000000000000000000000815" as const; +export const PRECOMPILE_IDENTITY_ADDRESS = "0x0000000000000000000000000000000000000818" as const; diff --git a/test/moonwall/helpers/precompile-contract-calls.ts b/test/moonwall/helpers/precompile-contract-calls.ts new file mode 100644 index 00000000..4753f08e --- /dev/null +++ b/test/moonwall/helpers/precompile-contract-calls.ts @@ -0,0 +1,136 @@ +/** + * Precompile contract call helpers + * Adapted from Moonbeam test suite + */ + +import type { BlockCreation, DevModeContext, PrecompileCallOptions } from "@moonwall/cli"; +import type { KeyringPair } from "@moonwall/util"; + +class PrecompileContract { + precompileName: string; + context: DevModeContext; + privateKey?: `0x${string}`; + gas?: bigint | "estimate"; + rawTxOnly?: boolean; + signer?: KeyringPair; + expectEvents?: [any]; + + constructor(precompileName: string, context: DevModeContext) { + this.precompileName = precompileName; + this.context = context; + this.reset(); + } + + reset() { + this.privateKey = undefined; + this.gas = undefined; + this.rawTxOnly = true; + this.signer = undefined; + this.expectEvents = undefined; + return this; + } + + withPrivateKey(privateKey: `0x${string}`) { + this.privateKey = privateKey; + return this; + } + + withGas(gas: bigint | "estimate") { + this.gas = gas; + return this; + } + + withRawTxOnly(rawTxOnly: boolean) { + if (rawTxOnly === false) { + this.rawTxOnly = undefined; + } + return this; + } + + withSigner(signer: KeyringPair) { + this.signer = signer; + return this; + } + + withExpectEvents(expectEvents: [any]) { + this.expectEvents = expectEvents; + return this; + } + + callExtrinsic(functionName: string, args: any[]): PrecompileCall { + return this.callRpc(functionName, args, true); + } + + callQuery(functionName: string, args: any[]): PrecompileCall { + return this.callRpc(functionName, args, false); + } + + private callRpc(functionName: string, args: any[], isExtrinsic: boolean): PrecompileCall { + const params = { + precompileName: this.precompileName, + functionName, + args, + privateKey: this.privateKey, + rawTxOnly: this.rawTxOnly, + gas: this.gas, + }; + const blockCreationOptions = { + signer: this.signer, + expectEvents: this.expectEvents, + }; + if (!isExtrinsic) { + return new ReadPrecompileCall(params, this.context, blockCreationOptions); + } + return new WritePrecompileCall(params, this.context, blockCreationOptions); + } +} + +export class PrecompileCall { + params: PrecompileCallOptions; + context: DevModeContext; + blockCreationOptions: BlockCreation; + + constructor( + params: PrecompileCallOptions, + context: DevModeContext, + blockCreationOptions: BlockCreation + ) { + this.params = params; + this.context = context; + this.blockCreationOptions = blockCreationOptions; + } + + async tx(): Promise { + throw new Error("Not implemented"); + } + + async block() { + return await this.context.createBlock((await this.tx()) as any, this.blockCreationOptions); + } +} + +class ReadPrecompileCall extends PrecompileCall { + async tx(): Promise { + return await this.context.readPrecompile!(this.params); + } +} + +class WritePrecompileCall extends PrecompileCall { + async tx(): Promise { + return await this.context.writePrecompile!(this.params); + } +} + +export class Preimage extends PrecompileContract { + constructor(context: DevModeContext) { + super("Preimage", context); + } + + notePreimage(data: string): PrecompileCall { + return this.callExtrinsic("notePreimage", [data]); + } + + unnotePreimage(data: string): PrecompileCall { + return this.callExtrinsic("unnotePreimage", [data]); + } +} diff --git a/test/moonwall/suites/dev/common/test-proxy/test-proxy-balance.ts b/test/moonwall/suites/dev/common/test-proxy/test-proxy-balance.ts new file mode 100644 index 00000000..371bb80d --- /dev/null +++ b/test/moonwall/suites/dev/common/test-proxy/test-proxy-balance.ts @@ -0,0 +1,80 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + CHARLETH_ADDRESS, + baltathar, +} from "@moonwall/util"; + +describeSuite({ + id: "D010502", + title: "Proxy: Balances", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should accept known proxy", + test: async () => { + const beforeCharlieBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + const { result } = await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(baltathar.address, "Balances" as any, 0) + ); + const proxyAdded = result!.events.find( + ({ event }) => event.method === "ProxyAdded" + ); + expect(proxyAdded).to.not.be.undefined; + expect(proxyAdded!.event.data[2].toString()).to.be.eq("Balances"); //ProxyType + expect(result!.events.some(({ event }) => event.method === "ExtrinsicSuccess")).to.be.true; + + const { result: result2 } = await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxy( + ALITH_ADDRESS, + null, + context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100) + ) + .signAsync(baltathar) + ); + + const proxyExecuted = result2!.events.find( + ({ event }) => event.method === "ProxyExecuted" + ); + expect(proxyExecuted).to.not.be.undefined; + expect(proxyExecuted!.event.data[0].toString()).to.be.eq("Ok"); + expect(result2!.events.some(({ event }) => event.method === "ExtrinsicSuccess")).to.be + .true; + const afterCharlieBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlieBalance - beforeCharlieBalance).to.be.eq(100n); + }, + }); + + it({ + id: "T02", + title: "shouldn't accept other proxy types", + test: async () => { + await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(baltathar.address, "Balances", 0) + ); + + const { result } = await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxy( + ALITH_ADDRESS, + null, + context.polkadotJs().tx.system.remark("0x") + ) + .signAsync(baltathar) + ); + + const proxyExecuted = result!.events.find( + ({ event }) => event.method === "ProxyExecuted" + ); + expect(proxyExecuted).to.not.be.undefined; + // Balances proxy type should not allow system.remark + expect(proxyExecuted!.event.data[0].toString()).to.not.be.eq("Ok"); + expect(result!.events.some(({ event }) => event.method === "ExtrinsicSuccess")).to.be.true; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/balance/test-balance-existential.ts b/test/moonwall/suites/dev/stagenet/balance/test-balance-existential.ts new file mode 100644 index 00000000..a64afb84 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/balance/test-balance-existential.ts @@ -0,0 +1,93 @@ +/** + * Existential deposit tests + * Adapted from Moonbeam test suite + */ + +import { expect, describeSuite, beforeEach, TransactionTypes } from "@moonwall/cli"; +import { ALITH_ADDRESS, baltathar, GLMR } from "@moonwall/util"; +import { createRawTransfer } from "@moonwall/util"; +import { Wallet } from "ethers"; +import { ConstantStore } from "../../../../helpers"; + +describeSuite({ + id: "D030203", + title: "Existential Deposit", + foundationMethods: "dev", + testCases: ({ context, log, it }) => { + let privateKey: `0x${string}`; + let randomWeb3Account: any; + let GENESIS_BASE_FEE: bigint; + + beforeEach(async function () { + const { specVersion } = await context.polkadotJs().consts.system.version; + GENESIS_BASE_FEE = ConstantStore(context).GENESIS_BASE_FEE.get(specVersion.toNumber()); + + randomWeb3Account = context.web3().eth.accounts.create(); + privateKey = randomWeb3Account.privateKey; + const { result } = await context.createBlock( + context.polkadotJs().tx.balances.transferAllowDeath(randomWeb3Account.address, 10n * GLMR) + ); + expect(result!.successful, result!.error?.name).to.be.true; + }); + + for (const txnType of TransactionTypes) { + it({ + id: `T0${TransactionTypes.indexOf(txnType) + 1}`, + title: `full ${txnType} transfer should not reap on 0 account balance`, + test: async function () { + const raw = await createRawTransfer( + context, + ALITH_ADDRESS, + 10n * GLMR - 21000n * GENESIS_BASE_FEE, + { + privateKey, + type: txnType, + gasPrice: GENESIS_BASE_FEE, + gas: 21000n, + maxFeePerGas: GENESIS_BASE_FEE, + } + ); + const { result } = await context.createBlock(raw); + + expect( + await context.viem().getTransactionCount({ address: randomWeb3Account.address }) + ).toBe(1); + expect(result!.successful, result!.error?.name).toBe(true); + expect(await context.viem().getBalance({ address: randomWeb3Account.address })).toBe(0n); + }, + }); + } + + it({ + id: "T04", + title: "should not reap on tiny balance", + test: async function () { + const signer = new Wallet(privateKey, context.ethers().provider); + await signer.sendTransaction({ + to: baltathar.address, + value: 10n * GLMR - 21000n * GENESIS_BASE_FEE - 1n, + gasPrice: GENESIS_BASE_FEE, + gasLimit: 21000n, + }); + + await context.createBlock(); + + expect(await context.viem().getBalance({ address: randomWeb3Account.address })).toBe(1n); + expect( + await context.viem().getTransactionCount({ address: randomWeb3Account.address }) + ).toBe(1); + }, + }); + + it({ + id: "T05", + title: "runtime constant should be set to zero", + test: async function () { + const existentialDeposit = context + .polkadotJs() + .consts.balances.existentialDeposit.toBigInt(); + expect(existentialDeposit).toBe(0n); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/balance/test-balance-extrinsics.ts b/test/moonwall/suites/dev/stagenet/balance/test-balance-extrinsics.ts new file mode 100644 index 00000000..7704c1fe --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/balance/test-balance-extrinsics.ts @@ -0,0 +1,87 @@ +/** + * Balance extrinsics tests + * Adapted from Moonbeam test suite + */ + +import { TransactionTypes, beforeAll, beforeEach, describeSuite, expect } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + BALTATHAR_ADDRESS, + GLMR, + createRawTransfer, + mapExtrinsics, +} from "@moonwall/util"; +import type { PrivateKeyAccount } from "viem"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; + +describeSuite({ + id: "D030204", + title: "Balance - Extrinsic Events", + foundationMethods: "dev", + testCases: ({ context, log, it }) => { + let randomAccount: PrivateKeyAccount; + + beforeAll(async function () { + // To create the treasury account + await context.createBlock(createRawTransfer(context, BALTATHAR_ADDRESS, 1337)); + }); + + beforeEach(async function () { + const privateKey = generatePrivateKey(); + randomAccount = privateKeyToAccount(privateKey); + }); + + for (const txnType of TransactionTypes) { + it({ + id: `T0${TransactionTypes.indexOf(txnType) + 1}`, + title: `should emit events for ${txnType} ethereum/transfers`, + test: async function () { + await context.createBlock( + createRawTransfer(context, randomAccount.address, 1n * GLMR, { + type: txnType, + gas: 500000n, + }) + ); + + const signedBlock = await context.polkadotJs().rpc.chain.getBlock(); + const allRecords = await context.polkadotJs().query.system.events(); + const txsWithEvents = mapExtrinsics(signedBlock.block.extrinsics, allRecords); + + const ethTx = txsWithEvents.find( + ({ extrinsic: { method } }) => method.section === "ethereum" + )!; + + // Check key events are present + const hasNewAccount = ethTx.events.some((e) => + context.polkadotJs().events.system.NewAccount.is(e) + ); + const hasEndowed = ethTx.events.some((e) => + context.polkadotJs().events.balances.Endowed.is(e) + ); + const hasTransfer = ethTx.events.some((e) => + context.polkadotJs().events.balances.Transfer.is(e) + ); + const hasExecuted = ethTx.events.some((e) => + context.polkadotJs().events.ethereum.Executed.is(e) + ); + const hasSuccess = ethTx.events.some((e) => + context.polkadotJs().events.system.ExtrinsicSuccess.is(e) + ); + + expect(hasNewAccount, "NewAccount event should be present").to.be.true; + expect(hasEndowed, "Endowed event should be present").to.be.true; + expect(hasTransfer, "Transfer event should be present").to.be.true; + expect(hasExecuted, "Executed event should be present").to.be.true; + expect(hasSuccess, "ExtrinsicSuccess event should be present").to.be.true; + + // Verify transfer event data + const transferEvent = ethTx.events.find((e) => + context.polkadotJs().events.balances.Transfer.is(e) + )!; + expect(transferEvent.data[0].toString()).to.eq(ALITH_ADDRESS); + expect(transferEvent.data[1].toString()).to.eq(randomAccount.address); + }, + }); + } + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/balance/test-balance-genesis.ts b/test/moonwall/suites/dev/stagenet/balance/test-balance-genesis.ts new file mode 100644 index 00000000..41762f3b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/balance/test-balance-genesis.ts @@ -0,0 +1,38 @@ +import "@moonbeam-network/api-augment"; +import { expect, describeSuite } from "@moonwall/cli"; +import { ALITH_ADDRESS } from "@moonwall/util"; +import { + ALITH_GENESIS_FREE_BALANCE, + ALITH_GENESIS_RESERVE_BALANCE, + ALITH_GENESIS_TRANSFERABLE_BALANCE, +} from "../../../../helpers"; + +describeSuite({ + id: "D030201", + title: "Balance genesis", + foundationMethods: "dev", + testCases: ({ context, it }) => { + it({ + id: "T01", + title: "should be accessible through web3", + test: async function () { + expect(await context.viem().getBalance({ address: ALITH_ADDRESS })).toBe( + ALITH_GENESIS_TRANSFERABLE_BALANCE + ); + }, + }); + + it({ + id: "T02", + title: "should be accessible through polkadotJs", + test: async function () { + const genesisHash = await context.polkadotJs().rpc.chain.getBlockHash(0); + const account = await (await context.polkadotJs().at(genesisHash)).query.system.account( + ALITH_ADDRESS + ); + expect(account.data.free.toBigInt()).toBe(ALITH_GENESIS_FREE_BALANCE); + expect(account.data.reserved.toBigInt()).toBe(ALITH_GENESIS_RESERVE_BALANCE); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/balance/test-balance-transfer.ts b/test/moonwall/suites/dev/stagenet/balance/test-balance-transfer.ts new file mode 100644 index 00000000..9c49a53f --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/balance/test-balance-transfer.ts @@ -0,0 +1,242 @@ +import "@moonbeam-network/api-augment"; +import { beforeEach, describeSuite, expect } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + CHARLETH_ADDRESS, + BALTATHAR_ADDRESS, + BALTATHAR_PRIVATE_KEY, + CHARLETH_PRIVATE_KEY, + FAITH_PRIVATE_KEY, + GLMR, + checkBalance, + createViemTransaction, + createRawTransfer, + generateKeyringPair, + sendRawTransaction, +} from "@moonwall/util"; +import { + ALITH_GENESIS_TRANSFERABLE_BALANCE, + ConstantStore, + verifyLatestBlockFees, +} from "../../../../helpers"; + +import { parseGwei } from "viem"; + +describeSuite({ + id: "D030202", + title: "Balance Transfers", + foundationMethods: "dev", + testCases: ({ context, log, it }) => { + let randomAddress: `0x${string}`; + let GENESIS_BASE_FEE; + + beforeEach(async function () { + const randomAccount = generateKeyringPair(); + randomAddress = randomAccount.address as `0x${string}`; + const { specVersion } = await context.polkadotJs().consts.system.version; + GENESIS_BASE_FEE = ConstantStore(context).GENESIS_BASE_FEE.get(specVersion.toNumber()); + }); + + it({ + id: "T01", + title: "should cost 21000 gas for a transfer", + test: async function () { + const estimatedGas = await context.viem().estimateGas({ + account: ALITH_ADDRESS, + value: 0n * GLMR, + to: randomAddress, + }); + expect(estimatedGas, "Estimated bal transfer incorrect").toBe(21000n); + + await context.createBlock(createRawTransfer(context, randomAddress, 0n)); + expect(await context.viem().getBalance({ address: ALITH_ADDRESS })).toBe( + ALITH_GENESIS_TRANSFERABLE_BALANCE - 21000n * GENESIS_BASE_FEE + ); + }, + }); + + it({ + id: "T02", + title: "unsent txns should be in pending", + test: async function () { + await context.createBlock(); + const rawTx = (await createRawTransfer(context, randomAddress, 512n, { + privateKey: CHARLETH_PRIVATE_KEY, + gasPrice: GENESIS_BASE_FEE, + gas: 21000n, + txnType: "legacy", + })) as `0x${string}`; + await sendRawTransaction(context, rawTx); + + expect( + await context.viem().getBalance({ address: randomAddress, blockTag: "pending" }) + ).toBe(512n); + }, + }); + + it({ + id: "T03", + title: "should decrease from account", + test: async function () { + const balanceBefore = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + const fees = 21000n * GENESIS_BASE_FEE; + await context.createBlock( + await createRawTransfer(context, randomAddress, 512n, { + gas: 21000n, + gasPrice: GENESIS_BASE_FEE, + txnType: "legacy", + privateKey: CHARLETH_PRIVATE_KEY, + }) + ); + const balanceAfter = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(balanceBefore - balanceAfter - fees).toBe(512n); + }, + }); + + it({ + id: "T04", + title: "should increase to account", + test: async function () { + const balanceBefore = await checkBalance(context, randomAddress); + + await context.createBlock( + await createRawTransfer(context, randomAddress, 512n, { + gas: 21000n, + gasPrice: GENESIS_BASE_FEE, + type: "legacy", + }) + ); + const balanceAfter = await checkBalance(context, randomAddress); + expect(balanceBefore).toBe(0n); + expect(balanceAfter).toBe(512n); + }, + }); + + it({ + id: "T05", + title: "should reflect balance identically on polkadot/web3", + test: async function () { + await context.createBlock( + await createRawTransfer(context, randomAddress, 512n, { + gas: 21000n, + gasPrice: GENESIS_BASE_FEE, + type: "legacy", + }) + ); + + const blockNumber = ( + await context.polkadotJs().rpc.chain.getBlock() + ).block.header.number.toBigInt(); + + const block1Hash = await context.polkadotJs().rpc.chain.getBlockHash(blockNumber); + const balance = await (await context.polkadotJs().at(block1Hash)).query.system.account( + ALITH_ADDRESS + ); + + expect(await context.viem().getBalance({ blockNumber, address: ALITH_ADDRESS })).to.equal( + balance.data.free.toBigInt() + + balance.data.reserved.toBigInt() - + balance.data.frozen.toBigInt() + ); + }, + }); + + it({ + id: "T06", + title: "should check latest block fees", + test: async function () { + await context.createBlock( + await createRawTransfer(context, randomAddress, 512n, { + gas: 21000n, + gasPrice: GENESIS_BASE_FEE, + type: "legacy", + }) + ); + + await verifyLatestBlockFees(context, BigInt(512)); + }, + }); + + // NOTE: Uses FAITH_PRIVATE_KEY (aka Frank in DataHaven) instead of GERALD_PRIVATE_KEY + // because Gerald is not endowed at genesis in DataHaven (unlike Moonbeam). + it({ + id: "T07", + title: "multiple transfer should be successful", + test: async function () { + const { result } = await context.createBlock([ + await createRawTransfer(context, randomAddress, 10n * GLMR, { + privateKey: FAITH_PRIVATE_KEY, + nonce: 0, + }), + await createRawTransfer(context, randomAddress, 10n * GLMR, { + privateKey: FAITH_PRIVATE_KEY, + nonce: 1, + }), + await createRawTransfer(context, randomAddress, 10n * GLMR, { + privateKey: FAITH_PRIVATE_KEY, + nonce: 2, + }), + await createRawTransfer(context, randomAddress, 10n * GLMR, { + privateKey: FAITH_PRIVATE_KEY, + nonce: 3, + }), + await createRawTransfer(context, randomAddress, 10n * GLMR, { + privateKey: FAITH_PRIVATE_KEY, + nonce: 4, + }), + ]); + + expect((result as any).filter((r: any) => r.successful)).to.be.length(5); + }, + }); + + it({ + id: "T08", + title: "should handle max_fee_per_gas", + test: async function () { + const balanceBefore = await checkBalance(context, CHARLETH_ADDRESS); + await context.createBlock( + await createRawTransfer(context, randomAddress, 1n * GLMR, { + gas: 21000n, + maxFeePerGas: GENESIS_BASE_FEE, + maxPriorityFeePerGas: parseGwei("0.2"), + gasPrice: GENESIS_BASE_FEE, + type: "eip1559", + privateKey: CHARLETH_PRIVATE_KEY, + }) + ); + const balanceAfter = await checkBalance(context, CHARLETH_ADDRESS); + const fee = 21000n * GENESIS_BASE_FEE; + + expect(balanceAfter + fee + 1n * GLMR).toBe(balanceBefore); + }, + }); + + it({ + id: "T09", + title: "should use partial max_priority_fee_per_gas", + test: async function () { + // With this configuration only half of the priority fee will be used, + // as the max_fee_per_gas is 2GWEI and the base fee is 1GWEI. + const accountData = (await context.polkadotJs().query.system.account(BALTATHAR_ADDRESS)) + .data; + const freeBal = accountData.free.toBigInt() - accountData.reserved.toBigInt(); + const maxFeePerGas = 10_000_000_000n * 2n; + await context.createBlock( + await createViemTransaction(context, { + privateKey: BALTATHAR_PRIVATE_KEY, + gas: 21000n, + to: randomAddress, + data: "0x", + maxFeePerGas, + maxPriorityFeePerGas: maxFeePerGas, + type: "eip1559", + }) + ); + const balanceAfter = await checkBalance(context, BALTATHAR_ADDRESS); + const fee = 21_000n * maxFeePerGas; + expect(freeBal - balanceAfter - fee).toBe(0n); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/multisig/test-multisigs.ts b/test/moonwall/suites/dev/stagenet/multisig/test-multisigs.ts new file mode 100644 index 00000000..f760607b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/multisig/test-multisigs.ts @@ -0,0 +1,184 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { blake2AsHex, createKeyMulti } from "@polkadot/util-crypto"; +import { u8aToHex } from "@polkadot/util"; +import { + ALITH_ADDRESS, + BALTATHAR_ADDRESS, + CHARLETH_ADDRESS, + DOROTHY_ADDRESS, + alith, + baltathar, +} from "@moonwall/util"; + +// This test cases in this suite are dependent on each other, and must be run in order. +// TODO: Make the test cases atomic + +describeSuite({ + id: "D022101", + title: "Multisigs - perform multisigs operations", + foundationMethods: "dev", + testCases: ({ context, it }) => { + let threshold: number; + let call: any; + let encodedCall: string; + let encodedCallHash: string; + + // multisig accountId + let encodedMultisigId: Uint8Array; + let multisigId: string; + + beforeAll(async function () { + // set threshold and create multisig accountId + threshold = 2; + encodedMultisigId = createKeyMulti([ALITH_ADDRESS, BALTATHAR_ADDRESS, CHARLETH_ADDRESS], 2); + multisigId = u8aToHex(encodedMultisigId.slice(0, 20)); + + // encode and hash the call we want to dispatch as a multisig operation + call = context.polkadotJs().tx.balances.transferKeepAlive(DOROTHY_ADDRESS, 20); + encodedCall = call.method.toHex(); + encodedCallHash = blake2AsHex(encodedCall); + }); + + it({ + id: "T01", + title: "Should create a multisig operation with asMulti", + test: async () => { + // set signatories + const otherSignatories = [BALTATHAR_ADDRESS, CHARLETH_ADDRESS]; + const block = await context.createBlock( + context + .polkadotJs() + .tx.multisig.asMulti(threshold, otherSignatories, null, encodedCall, {}) + .signAsync(alith) + ); + + // check the event 'NewMultisig' was emitted + const records = await context.polkadotJs().query.system.events(); + const events = records.filter( + ({ event }) => event.section === "multisig" && event.method === "NewMultisig" + ); + expect(events).to.have.lengthOf(1); + expect(block.result!.successful).to.be.true; + }, + }); + + it({ + id: "T02", + title: "Should be able to approve a multisig operation with approveAsMulti", + test: async function () { + // signatories (sorted) + const otherSignatories = [CHARLETH_ADDRESS, ALITH_ADDRESS]; + // create a new multisig operation + await context.createBlock( + context + .polkadotJs() + .tx.multisig.asMulti(threshold, otherSignatories, null, encodedCall, {}) + .signAsync(alith), + { allowFailures: true } + ); + + // take the info of the new multisig operation saved in storage + const multisigInfo = await context + .polkadotJs() + .query.multisig.multisigs(multisigId, encodedCallHash); + const block = await context.createBlock( + context + .polkadotJs() + .tx.multisig.approveAsMulti( + threshold, + otherSignatories, + multisigInfo.unwrap().when, + encodedCallHash, + {} + ) + .signAsync(baltathar), + { allowFailures: true } + ); + + // check the event 'MultisigApproval' was emitted + const records = await context.polkadotJs().query.system.events(); + const events = records.filter( + ({ event }) => event.section === "multisig" && event.method === "MultisigApproval" + ); + expect(events).to.have.lengthOf(1); + expect(block.result!.successful).to.be.true; + }, + }); + + it({ + id: "T03", + title: "Should be able to cancel a multisig operation", + test: async () => { + const otherSignatories = [BALTATHAR_ADDRESS, CHARLETH_ADDRESS]; + // create a new multisig operation + await context.createBlock( + context + .polkadotJs() + .tx.multisig.asMulti(threshold, otherSignatories, null, encodedCall, {}) + .signAsync(alith), + { allowFailures: true } + ); + + // take the info of the new multisig operation saved in storage + const multisigInfo = await context + .polkadotJs() + .query.multisig.multisigs(multisigId, encodedCallHash); + const block = await context.createBlock( + context + .polkadotJs() + .tx.multisig.cancelAsMulti( + threshold, + otherSignatories, + multisigInfo.unwrap().when, + encodedCallHash + ) + .signAsync(alith) + ); + + const records = await context.polkadotJs().query.system.events(); + const events = records.filter( + ({ event }) => event.section === "multisig" && event.method === "MultisigCancelled" + ); + expect(events, "event 'MultisigCancelled' was not emitted").to.have.lengthOf(1); + expect(block.result!.successful).to.be.true; + }, + }); + + it({ + id: "T04", + title: "Should fail if signatories are out of order", + test: async () => { + const otherSignatories = [CHARLETH_ADDRESS, BALTATHAR_ADDRESS]; + const block = await context.createBlock( + context + .polkadotJs() + .tx.multisig.asMulti(threshold, otherSignatories, null, encodedCall, {}) + .signAsync(alith), + { allowFailures: true } + ); + expect(block.result!.error!.name, "signatories (they are not sorted)").to.equal( + "SignatoriesOutOfOrder" + ); + expect(block.result!.successful).to.be.false; + }, + }); + + it({ + id: "T05", + title: "Should fail if sender is present in signatories", + test: async () => { + // signatories (with sender in signatories) + const otherSignatories = [ALITH_ADDRESS, BALTATHAR_ADDRESS]; + const block = await context.createBlock( + context + .polkadotJs() + .tx.multisig.asMulti(threshold, otherSignatories, null, encodedCall, {}) + .signAsync(alith), + { allowFailures: true } + ); + expect(block.result!.error!.name).to.equal("SenderInSignatories"); + expect(block.result!.successful).to.be.false; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/node-rpc/test-node-rpc-peer.ts b/test/moonwall/suites/dev/stagenet/node-rpc/test-node-rpc-peer.ts new file mode 100644 index 00000000..e699fd94 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/node-rpc/test-node-rpc-peer.ts @@ -0,0 +1,21 @@ +import { customDevRpcRequest, describeSuite, expect } from "@moonwall/cli"; + +describeSuite({ + id: "D022201", + title: "Node - RPC", + foundationMethods: "dev", + testCases: ({ context, it }) => { + it({ + id: "T01", + title: "should report peer count in hex", + test: async function () { + // this tests that the "net_peerCount" response comes back in hex and not decimal. + // related: frontier commits 677548c and 78fb3bc + const result = await customDevRpcRequest("net_peerCount", []); + + expect(result).to.be.equal("0x0"); + expect(typeof result).to.be.equal("string"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/polkadot-js/test-polkadot-api.ts b/test/moonwall/suites/dev/stagenet/polkadot-js/test-polkadot-api.ts new file mode 100644 index 00000000..524a16c3 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/polkadot-js/test-polkadot-api.ts @@ -0,0 +1,141 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { ALITH_ADDRESS, GLMR, generateKeyringPair } from "@moonwall/util"; + +describeSuite({ + id: "D022501", + title: "Polkadot API", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should return genesis block", + test: async function () { + const lastHeader = await context.polkadotJs().rpc.chain.getHeader(); + expect(Number(lastHeader.number) >= 0).to.be.true; + }, + }); + + it({ + id: "T02", + title: "should return latest header number", + test: async function () { + await context.createBlock(); + const lastHeader = await context.polkadotJs().rpc.chain.getHeader(); + expect(lastHeader.number.toNumber()).to.be.at.least(1); + }, + }); + + it({ + id: "T03", + title: "transfers should be stored on chain", + test: async function () { + const randomAddress = generateKeyringPair().address as `0x${string}`; + await context.createBlock( + context.polkadotJs().tx.balances.transferAllowDeath(randomAddress, 2n * GLMR) + ); + + expect(BigInt(await context.viem().getBalance({ address: randomAddress }))).to.equal( + 2n * GLMR + ); + }, + }); + + it({ + id: "T04", + title: "should appear in extrinsics", + test: async function () { + const randomAddress = generateKeyringPair().address as `0x${string}`; + await context.createBlock( + context.polkadotJs().tx.balances.transferAllowDeath(randomAddress, 2n * GLMR) + ); + const signedBlock = await context.polkadotJs().rpc.chain.getBlock(); + + // Expecting 3 extrinsics so far: + // timestamp, author, the parachain validation data, randomness, and the balances transfer. + expect(signedBlock.block.extrinsics).to.be.of.length(3); + + signedBlock.block.extrinsics.forEach((ex, index) => { + const { + method: { args, method, section }, + } = ex; + const message = `${section}.${method}(${args.map((a) => a.toString()).join(", ")})`; + + switch (index) { + case 0: + expect(message.substring(0, 13)).to.eq(`timestamp.set`); + break; + case 1: + expect(message.toLocaleLowerCase()).to.match(/^randomness\.setbaberandomness/); + break; + case 2: + expect(message).to.eq( + `balances.transferAllowDeath(${randomAddress}, 2000000000000000000)` + ); + expect(ex.signer.toString()).to.eq(ALITH_ADDRESS); + break; + default: + throw new Error(`Unexpected extrinsic: ${message}`); + } + }); + }, + }); + + it({ + id: "T05", + title: "should appear in events", + test: async function () { + // Generating two transfers to ensure treasury account exists + const randomAddress = generateKeyringPair().address as `0x${string}`; + await context.createBlock( + context.polkadotJs().tx.balances.transferAllowDeath(randomAddress, 2n * GLMR) + ); + + const randomAddress2 = generateKeyringPair().address as `0x${string}`; + await context.createBlock( + context.polkadotJs().tx.balances.transferAllowDeath(randomAddress2, 2n * GLMR) + ); + const signedBlock = await context.polkadotJs().rpc.chain.getBlock(); + const apiAt = await context.polkadotJs().at(signedBlock.block.header.hash); + const allRecords = await apiAt.query.system.events(); + + // map between the extrinsics and events + signedBlock.block.extrinsics.forEach((_, index) => { + // filter the specific events based on the phase and then the + // index of our extrinsic in the block + const events = allRecords + .filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index)) + .map(({ event }) => event); + + switch (index) { + // First 2 events: + // timestamp.set:: system.ExtrinsicSuccess + // randomness.setBabeRandomness:: system.ExtrinsicSuccess + case 0: + case 1: + expect(events).to.be.of.length(1); + expect(context.polkadotJs().events.system.ExtrinsicSuccess.is(events[0])).to.be.true; + break; + // balances.transferAllowDeath emits: system.NewAccount, balances.Endowed, + // balances.Transfer, (other events), system.ExtrinsicSuccess + case 2: + log(events.map((e) => `${e.section}.${e.method}`).join(" - ")); + expect(events.length).to.be.at.least(7); + expect(events.some((e) => context.polkadotJs().events.system.NewAccount.is(e))).to.be + .true; + expect(events.some((e) => context.polkadotJs().events.balances.Endowed.is(e))).to.be + .true; + expect(events.some((e) => context.polkadotJs().events.balances.Transfer.is(e))).to.be + .true; + // ExtrinsicSuccess should be the last event + expect( + context.polkadotJs().events.system.ExtrinsicSuccess.is(events[events.length - 1]) + ).to.be.true; + break; + default: + throw new Error(`Unexpected extrinsic`); + } + }); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/polkadot-js/test-polkadot-chain-info.ts b/test/moonwall/suites/dev/stagenet/polkadot-js/test-polkadot-chain-info.ts new file mode 100644 index 00000000..64b5455a --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/polkadot-js/test-polkadot-chain-info.ts @@ -0,0 +1,21 @@ +import { customDevRpcRequest, describeSuite, expect } from "@moonwall/cli"; + +describeSuite({ + id: "D022502", + title: "Web3Api Information", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should include client version", + test: async function () { + const version = (await customDevRpcRequest("web3_clientVersion", [])) as string; + const specName = context.polkadotJs().runtimeVersion.specName.toString(); + const specVersion = context.polkadotJs().runtimeVersion.specVersion.toString(); + const implVersion = context.polkadotJs().runtimeVersion.implVersion.toString(); + const expected = `${specName}/v${specVersion}.${implVersion}/fc-rpc-2.0.0-dev`; + expect(version).toBe(expected); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-blake2.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-blake2.ts new file mode 100644 index 00000000..c936fd84 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-blake2.ts @@ -0,0 +1,37 @@ +/** + * Blake2 precompile tests + * Adapted from Moonbeam test suite + */ + +import { deployCreateCompiledContract, describeSuite } from "@moonwall/cli"; +import { expectEVMResult } from "../../../../helpers"; + +import { createViemTransaction } from "@moonwall/util"; +import { encodeFunctionData } from "viem"; + +describeSuite({ + id: "D030101", + title: "Precompiles - blake2", + foundationMethods: "dev", + testCases: ({ context, log, it }) => { + it({ + id: "T01", + title: "should be accessible from a smart contract", + test: async function () { + const { abi } = await deployCreateCompiledContract(context, "HasherChecker"); + + // Execute the contract blake2 call + const { result } = await context.createBlock( + createViemTransaction(context, { + data: encodeFunctionData({ + abi, + functionName: "blake2Check", + }), + }) + ); + + expectEVMResult(result!.events, "Succeed"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128-bounds.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128-bounds.ts new file mode 100644 index 00000000..4ee0e5b8 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128-bounds.ts @@ -0,0 +1,80 @@ +import { describeSuite } from "@moonwall/cli"; +import { createViemTransaction, sendRawTransaction } from "@moonwall/util"; +/* + * These test cases trigger bugs in the bn128 precompiles which perform a from_slice() + * call on unchecked input. + * + * Fixed by: + * https://github.com/paritytech/frontier/pull/394 + */ + +describeSuite({ + id: "D022703", + title: "Precompiles - bn128 bounds", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should fail gracefully (case 1)", + test: async () => { + // some call data which will cause bn128 to be called with insufficient input. this + // presumably was generated through fuzzing. + const data = + ("0x608060405234801561001057600080fd5b5060008060405180608001604052807f2243525c5eda" + + "1401003c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703815260207f6e01001d33be6da800" + + "00002bcc35964723180eed75f91a010001007d48f195c91581526020017f18b18acfb4c2c30276db" + + "5411000000000000000b4691610c5d3b00010001b17f81526020017f063c909c4720840cb5134cb9" + + "f546c80200579d040100d32efc0d288197f37266815246475b6100bf61044d505b6040604b808460" + + "006007600019f1925082610142576000000000acd401000000000000000000000000000000000000" + + "000000000000000000008152600401808060200182810300192c748252601e8152602001887f656c" + + "6c967074000381327572766520616464ad74696f6e206661696c6564000081525060200191500000" + + "000000000009fd5b7f2bd3e6d0f3b142924f5ca7b49ce5b9d585420400ae5648e61d02268b1a0a9f" + + "b7816000600202020202020202020202020202020202fd0202020203020202020202020202020202" + + "0202fb02020a02020202020202020202020202020202020202020202020202020202020202020202" + + "02020202020200000000000000000a1c000000000000000000000000000000000000000901010037" + + "190100000000000000000000f81a0100000002020202020202020202020202020202020202028a30" + + "a82123b27db75200aedc4a45a0e84fbd1f9f3621350bb778119630350eb7a7e613058daf51e9f514" + + "8ea65715eaac3d8019f80498112fc4860a020202020202020202fd02020202020202020202020202" + + "02020202020202020202020202020202020202020202020202020202020202020202020202020212" + + "02020202020202020202010202fd0202020202020202020202020202020202020202020202020202" + + "020202020202020202020202005f02d2020202020202020202020202020202020202020202020202" + + "02020202020202020202020302020202020202020202020202020202020202020202020202020202" + + "0302020202020202020202020202") as `0x${string}`; + + const tx = await createViemTransaction(context, { + to: "0x0000000000000000000000000000000000000007", + data, + skipEstimation: true, + }); + + await sendRawTransaction(context, tx); + + // we expect that the node hasn't crashed by here. without a fix, the previous web3 request + // would have been sufficient to crash our node. now it fails with "ExhaustsResources". if + // we can create a block, we must not have crashed. + await context.createBlock(); + }, + }); + + it({ + id: "T02", + title: "should fail gracefully (case 2)", + test: async () => { + // similar to the above call data, although triggers a slightly different bug + + const tx = await createViemTransaction(context, { + to: "0x0000000000000000000000000000000000000007", + data: "0x0000000000000000000000000000000000000000050000000000008303d0300d901401", + skipEstimation: true, + }); + + await sendRawTransaction(context, tx); + + // we expect that the node hasn't crashed by here. without a fix, the previous web3 request + // would have been sufficient to crash our node. now it fails with "ExhaustsResources". if + // we can create a block, we must not have crashed. + await context.createBlock(); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128add.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128add.ts new file mode 100644 index 00000000..9e7c455a --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128add.ts @@ -0,0 +1,39 @@ +/** + * BN128 addition precompile tests + * Adapted from Moonbeam test suite + */ + +import { deployCreateCompiledContract, describeSuite } from "@moonwall/cli"; +import { createViemTransaction } from "@moonwall/util"; +import { encodeFunctionData } from "viem"; +import { expectEVMResult } from "../../../../helpers"; + +describeSuite({ + id: "D030102", + title: "Precompiles - bn128add", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should be accessible from a smart contract", + test: async function () { + const { abi, contractAddress } = await deployCreateCompiledContract( + context, + "HasherChecker" + ); + + const { result } = await context.createBlock( + createViemTransaction(context, { + to: contractAddress, + data: encodeFunctionData({ + abi, + functionName: "bn128AdditionCheck", + }), + }) + ); + + expectEVMResult(result!.events, "Succeed"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128mul.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128mul.ts new file mode 100644 index 00000000..ffd0144b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128mul.ts @@ -0,0 +1,39 @@ +/** + * BN128 multiplication precompile tests + * Adapted from Moonbeam test suite + */ + +import { deployCreateCompiledContract, describeSuite } from "@moonwall/cli"; +import { createViemTransaction } from "@moonwall/util"; +import { encodeFunctionData } from "viem"; +import { expectEVMResult } from "../../../../helpers"; + +describeSuite({ + id: "D030103", + title: "Precompiles - bn128mul", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should be accessible from a smart contract", + test: async function () { + const { abi, contractAddress } = await deployCreateCompiledContract( + context, + "HasherChecker" + ); + + const { result } = await context.createBlock( + createViemTransaction(context, { + to: contractAddress, + data: encodeFunctionData({ + abi, + functionName: "bn128MultiplyCheck", + }), + }) + ); + + expectEVMResult(result!.events, "Succeed"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128pairing.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128pairing.ts new file mode 100644 index 00000000..dd65daad --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-bn128pairing.ts @@ -0,0 +1,39 @@ +/** + * BN128 pairing precompile tests + * Adapted from Moonbeam test suite + */ + +import { deployCreateCompiledContract, describeSuite } from "@moonwall/cli"; +import { createViemTransaction } from "@moonwall/util"; +import { encodeFunctionData } from "viem"; +import { expectEVMResult } from "../../../../helpers"; + +describeSuite({ + id: "D030104", + title: "Precompiles - bn128pairing", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should be accessible from a smart contract", + test: async function () { + const { abi, contractAddress } = await deployCreateCompiledContract( + context, + "HasherChecker" + ); + + const { result } = await context.createBlock( + createViemTransaction(context, { + to: contractAddress, + data: encodeFunctionData({ + abi, + functionName: "bn128PairingCheck", + }), + }) + ); + + expectEVMResult(result!.events, "Succeed"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-ecrecover.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-ecrecover.ts new file mode 100644 index 00000000..5a7ef7c4 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-ecrecover.ts @@ -0,0 +1,81 @@ +/** + * Ecrecover precompile tests + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { ALITH_ADDRESS, ALITH_PRIVATE_KEY } from "@moonwall/util"; + +describeSuite({ + id: "D030107", + title: "Precompiles - ecrecover", + foundationMethods: "dev", + testCases: ({ context, log, it }) => { + let contractAddress: `0x${string}`; + + beforeAll(async function () { + const { contractAddress: deployedAddr } = await context.deployContract!("RecoveryChecker"); + contractAddress = deployedAddr; + }); + + it({ + id: "T01", + title: "returns a matching address", + test: async function () { + const msg = context.web3().utils.sha3("Hello World!"); + const sig = context.web3().eth.accounts.sign(msg!, ALITH_PRIVATE_KEY); + + const address = await context.readContract!({ + contractAddress, + contractName: "RecoveryChecker", + functionName: "checkRecovery", + args: [sig.messageHash, sig.v, sig.r, sig.s], + }); + + expect(address, "Recovered address doesn't match signer!").to.equals(ALITH_ADDRESS); + }, + }); + + it({ + id: "T02", + title: "returns different address on modified message", + test: async function () { + const msg = context.web3().utils.sha3("Hello World!"); + const sig = context.web3().eth.accounts.sign(msg!, ALITH_PRIVATE_KEY); + + const address = await context.readContract!({ + contractAddress, + contractName: "RecoveryChecker", + functionName: "checkRecovery", + args: [sig.messageHash.replace("1", "f"), sig.v, sig.r, sig.s], + }); + + expect(address, "Recovered address doesn't match signer!").to.equals( + "0x58188b9AE77F7C865b04B12F5D29bF4fbDcbd937" + ); + }, + }); + + it({ + id: "T03", + title: "returns empty on invalid V", + test: async function () { + const msg = context.web3().utils.sha3("Hello World!"); + const sig = context.web3().eth.accounts.sign(msg!, ALITH_PRIVATE_KEY); + const v = "0x565656ff5656ffffffffffff3d3d02000000000040003dffff565656560f0000"; + + await expect( + async () => + await context.readContract!({ + contractAddress, + contractName: "RecoveryChecker", + functionName: "checkRecovery", + args: [sig.messageHash, v, sig.r, sig.s], + web3Library: "ethers", + gas: 1_000_000n, + }) + ).rejects.toThrowError("revert"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-erc20-overflow.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-erc20-overflow.ts new file mode 100644 index 00000000..0409f157 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-erc20-overflow.ts @@ -0,0 +1,31 @@ +import "@moonbeam-network/api-augment"; +import { describeSuite, expect } from "@moonwall/cli"; +import { generateKeyringPair } from "@moonwall/util"; + +describeSuite({ + id: "D030402", + title: "Precompile ERC20 - Transfering through precompile", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + const randomAccount = generateKeyringPair(); + it({ + id: "T01", + title: "should not allow overflowing the value", + test: async function () { + await expect( + async () => + await context.writePrecompile!({ + precompileName: "Batch", + functionName: "batchAll", + args: [ + [randomAccount.address], + [`${(2n ** 128n + 5_000_000_000_000_000_000n).toString()}`], + [], + [], + ], + }) + ).rejects.toThrowError("evm error: OutOfFund"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-erc20.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-erc20.ts new file mode 100644 index 00000000..0d9a132d --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-erc20.ts @@ -0,0 +1,291 @@ +import "@moonbeam-network/api-augment"; +import { beforeEach, describeSuite, expect } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + BALTATHAR_ADDRESS, + BALTATHAR_PRIVATE_KEY, + CHARLETH_ADDRESS, + PRECOMPILE_NATIVE_ERC20_ADDRESS, + baltathar, +} from "@moonwall/util"; +import { type PrivateKeyAccount, keccak256, pad, parseEther, toBytes, toHex } from "viem"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { ALITH_GENESIS_TRANSFERABLE_BALANCE } from "../../../../helpers"; + +// const SELECTORS = { +// balanceOf: "70a08231", +// totalSupply: "18160ddd", +// approve: "095ea7b3", +// allowance: "dd62ed3e", +// transfer: "a9059cbb", +// transferFrom: "23b872dd", +// deposit: "d0e30db0", +// logApprove: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", +// logTransfer: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", +// }; + +// Error(string) +const ABI_REVERT_SELECTOR = "0x08c379a0"; + +describeSuite({ + id: "D030401", + title: "Precompiles - ERC20 Native", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let randomAccount: PrivateKeyAccount; + + beforeEach(async () => { + randomAccount = privateKeyToAccount(generatePrivateKey()); + }); + + it({ + id: "T01", + title: "allows to call getBalance", + test: async function () { + const balance = await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "balanceOf", + args: [ALITH_ADDRESS], + }); + + const signedTx = context + .polkadotJs() + .tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 1000) + .signAsync(baltathar); + await context.createBlock(signedTx); + + const tx = context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 1000); + await context.createBlock(tx, { + signer: { privateKey: BALTATHAR_PRIVATE_KEY, type: "ethereum" }, + }); + + expect(balance).equals(ALITH_GENESIS_TRANSFERABLE_BALANCE); + }, + }); + + it({ + id: "T02", + title: "allows to call totalSupply", + test: async function () { + const totalSupply = await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "totalSupply", + }); + + const totalIssuance = ( + await context.polkadotJs().query.balances.totalIssuance() + ).toBigInt(); + expect(totalSupply).toBe(totalIssuance); + }, + }); + + it({ + id: "T03", + title: "allows to approve transfers, and allowance matches", + test: async function () { + const allowanceBefore = (await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "allowance", + args: [ALITH_ADDRESS, BALTATHAR_ADDRESS], + })) as bigint; + const amount = parseEther("10"); + + const rawTx = await context.writePrecompile!({ + precompileName: "NativeErc20", + functionName: "approve", + args: [BALTATHAR_ADDRESS, amount], + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + + const allowanceAfter = (await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "allowance", + args: [ALITH_ADDRESS, BALTATHAR_ADDRESS], + })) as bigint; + + expect(allowanceAfter - allowanceBefore).equals(BigInt(amount)); + + const { status, logs } = await context + .viem() + .getTransactionReceipt({ hash: result?.hash as `0x${string}` }); + + expect(status).to.equal("success"); + expect(logs.length).to.eq(1); + expect(logs[0].topics[0]).toBe(keccak256(toBytes("Approval(address,address,uint256)"))); + expect(logs[0].topics[1]?.toLowerCase()).toBe( + pad(ALITH_ADDRESS.toLowerCase() as `0x${string}`) + ); + expect(logs[0].topics[2]?.toLowerCase()).toBe( + pad(BALTATHAR_ADDRESS.toLowerCase() as `0x${string}`) + ); + }, + }); + + it({ + id: "T04", + title: "allows to call transfer", + test: async function () { + expect( + await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "balanceOf", + args: [randomAccount.address], + }) + ).equals(0n); + + const balanceBefore = await context.viem().getBalance({ address: BALTATHAR_ADDRESS }); + + const rawTx = await context.writePrecompile!({ + precompileName: "NativeErc20", + functionName: "transfer", + args: [randomAccount.address, parseEther("3")], + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + const { status, gasUsed } = await context + .viem() + .getTransactionReceipt({ hash: result?.hash as `0x${string}` }); + expect(status).to.equal("success"); + + const balanceAfter = await context.viem().getBalance({ address: BALTATHAR_ADDRESS }); + const block = await context.viem().getBlock(); + const fees = gasUsed * block.baseFeePerGas!; + expect(balanceAfter).toBeLessThanOrEqual(balanceBefore - parseEther("3") - fees); + expect(await context.viem().getBalance({ address: randomAccount.address })).to.equal( + parseEther("3") + ); + }, + }); + + it({ + id: "T05", + title: "allows to approve transfer and use transferFrom", + test: async function () { + const allowedAmount = parseEther("10"); + const transferAmount = parseEther("5"); + + await context.writePrecompile!({ + precompileName: "NativeErc20", + functionName: "approve", + args: [BALTATHAR_ADDRESS, allowedAmount], + }); + await context.createBlock(); + + const fromBalBefore = ( + await context.polkadotJs().query.system.account(ALITH_ADDRESS) + ).data.free.toBigInt(); + const toBalBefore = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + + const rawTx = await context.writePrecompile!({ + precompileName: "NativeErc20", + functionName: "transferFrom", + args: [ALITH_ADDRESS, CHARLETH_ADDRESS, transferAmount], + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + }); + + const { result } = await context.createBlock(rawTx); + const { logs, status } = await context + .viem() + .getTransactionReceipt({ hash: result?.hash as `0x${string}` }); + + const fromBalAfter = ( + await context.polkadotJs().query.system.account(ALITH_ADDRESS) + ).data.free.toBigInt(); + + const toBalAfter = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(logs.length).to.eq(1); + expect(logs[0].address).to.eq(PRECOMPILE_NATIVE_ERC20_ADDRESS); + expect(logs[0].data).to.eq(pad(toHex(transferAmount))); + expect(logs[0].topics.length).to.eq(3); + expect(logs[0].topics[0]).toBe(keccak256(toBytes("Transfer(address,address,uint256)"))); + expect(logs[0].topics[1]?.toLowerCase()).toBe( + pad(ALITH_ADDRESS.toLowerCase() as `0x${string}`) + ); + expect(logs[0].topics[2]?.toLowerCase()).toBe( + pad(CHARLETH_ADDRESS.toLowerCase() as `0x${string}`) + ); + expect(status).to.equal("success"); + expect(toBalAfter).toBe(toBalBefore + transferAmount); + expect(fromBalAfter).toBe(fromBalBefore - transferAmount); + const newAllowedAmount = allowedAmount - transferAmount; + expect( + await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "allowance", + args: [ALITH_ADDRESS, BALTATHAR_ADDRESS], + }) + ).toBe(newAllowedAmount); + }, + }); + + it({ + id: "T06", + title: "refuses to transferFrom more than allowed", + test: async function () { + const allowedAmount = parseEther("10"); + const transferAmount = parseEther("15"); + + await context.writePrecompile!({ + precompileName: "NativeErc20", + functionName: "approve", + args: [BALTATHAR_ADDRESS, allowedAmount], + }); + await context.createBlock(); + + const fromBalBefore = ( + await context.polkadotJs().query.system.account(ALITH_ADDRESS) + ).data.free.toBigInt(); + const toBalBefore = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + + const rawTxn = await context.writePrecompile!({ + precompileName: "NativeErc20", + functionName: "transferFrom", + args: [ALITH_ADDRESS, CHARLETH_ADDRESS, transferAmount], + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + gas: 200_000n, + web3Library: "ethers", + }); + + const { result } = await context.createBlock(rawTxn); + expect(result?.successful).toBe(false); + + const fromBalAfter = ( + await context.polkadotJs().query.system.account(ALITH_ADDRESS) + ).data.free.toBigInt(); + + const toBalAfter = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(toBalAfter).toBe(toBalBefore); + expect(fromBalAfter).toBe(fromBalBefore); + expect( + await context.readPrecompile!({ + precompileName: "NativeErc20", + functionName: "allowance", + args: [ALITH_ADDRESS, BALTATHAR_ADDRESS], + }) + ).toBe(allowedAmount); + }, + }); + }, +}); + +// describeDevMoonbeamAllEthTxTypes("Precompiles - ERC20 Native", (context) => { +// it("revert message is abi-encoded as a String(error) call", async function () { +// const request = await web3EthCall(context.web3, { +// to: PRECOMPILE_NATIVE_ERC20_ADDRESS, +// data: `0x${SELECTORS.deposit}`, +// }); +// expect(request as any).to.haveOwnProperty("error"); +// // Data +// let data = (request as any).error.data; +// expect(data.length).to.be.eq(266); +// expect(data.slice(0, 10)).to.be.eq(ABI_REVERT_SELECTOR); +// // Message +// expect((request as any).error.message).to.be.eq( +// "VM Exception while processing transaction: revert deposited amount must be non-zero" +// ); +// }); +// }); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity.ts new file mode 100644 index 00000000..d5921eae --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity.ts @@ -0,0 +1,116 @@ +/** + * Identity precompile tests - retrieve registrars and identity + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { alith, baltathar } from "@moonwall/util"; +import { toHex } from "viem"; +import { PRECOMPILE_IDENTITY_ADDRESS } from "../../../../helpers"; + +describeSuite({ + id: "D030301", + title: "Precompiles - Identity precompile", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + + await context.createBlock(context.polkadotJs().tx.identity.setFee(0, 100)); + await context.createBlock( + // With 0b111 we are indicating the pallet to use "Display", "Legal" and "Web" fields. + context + .polkadotJs() + .tx.identity.setFields(0, 0b111 as any) + ); + + await context.createBlock( + context + .polkadotJs() + .tx.identity.setIdentity({ + additional: [[{ raw: "discord" }, { raw: "my-discord" }]], + display: { raw: "display" }, + legal: { raw: "legal" }, + web: { raw: "web" }, + riot: { raw: "riot" }, + email: { raw: "email" }, + pgpFingerprint: new Array(20).fill(1), + image: { raw: "image" }, + twitter: { raw: "twitter" }, + }) + .signAsync(baltathar) + ); + }); + + it({ + id: "T01", + title: "should retrieve registrars", + test: async function () { + const registrars = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "registrars", + args: [], + })) as any; + + expect(registrars.length).to.equal(1); + expect(registrars[0].isValid).to.be.true; + expect(registrars[0].index).to.equal(0); + expect(registrars[0].account).to.equal(alith.address); + expect(registrars[0].fee).to.equal(100n); + expect(registrars[0].fields.display).to.be.true; + expect(registrars[0].fields.web).to.be.true; + expect(registrars[0].fields.legal).to.be.true; + expect(registrars[0].fields.riot).to.be.false; + expect(registrars[0].fields.email).to.be.false; + expect(registrars[0].fields.pgpFingerprint).to.be.false; + expect(registrars[0].fields.image).to.be.false; + expect(registrars[0].fields.twitter).to.be.false; + }, + }); + + it({ + id: "T02", + title: "should retrieve identity", + test: async function () { + const identity = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "identity", + args: [baltathar.address], + })) as any; + + expect(identity.isValid).to.be.true; + expect(identity.judgements).to.be.empty; + expect(identity.deposit).to.equal(1034200000000000000n); + expect(identity.info.additional.length).to.equal(1); + expect(identity.info.additional[0].key.hasData).to.be.true; + expect(identity.info.additional[0].key.value).to.equal(toHex("discord")); + expect(identity.info.additional[0].value.hasData).to.be.true; + expect(identity.info.additional[0].value.value).to.equal(toHex("my-discord")); + expect(identity.info.display.hasData).to.be.true; + expect(identity.info.display.value).to.equal(toHex("display")); + expect(identity.info.legal.hasData).to.be.true; + expect(identity.info.legal.value).to.equal(toHex("legal")); + expect(identity.info.web.hasData).to.be.true; + expect(identity.info.web.value).to.equal(toHex("web")); + expect(identity.info.riot.hasData).to.be.true; + expect(identity.info.riot.value).to.equal(toHex("riot")); + expect(identity.info.email.hasData).to.be.true; + expect(identity.info.email.value).to.equal(toHex("email")); + expect(identity.info.hasPgpFingerprint).to.be.true; + expect(identity.info.pgpFingerprint).to.equal( + toHex(Uint8Array.from(new Array(20).fill(1))) + ); + expect(identity.info.image.hasData).to.be.true; + expect(identity.info.image.value).to.equal(toHex("image")); + expect(identity.info.twitter.hasData).to.be.true; + expect(identity.info.twitter.value).to.equal(toHex("twitter")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity10.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity10.ts new file mode 100644 index 00000000..d58b871b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity10.ts @@ -0,0 +1,61 @@ +/** + * Identity precompile tests - set account id + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { alith, charleth } from "@moonwall/util"; +import { expectEVMResult, PRECOMPILE_IDENTITY_ADDRESS } from "../../../../helpers"; + +describeSuite({ + id: "D030310", + title: "Precompiles - Identity precompile - set account id", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "setAccountId", + rawTxOnly: true, + args: [0, charleth.address], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + }); + + it({ + id: "T01", + title: "should retrieve the registrar", + test: async function () { + const registrars = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "registrars", + })) as any; + + expect(registrars.length).to.equal(1); + expect(registrars[0].isValid).to.be.true; + expect(registrars[0].index).to.equal(0); + expect(registrars[0].account).to.equal(charleth.address); + expect(registrars[0].fee).to.equal(0n); + expect(registrars[0].fields.display).to.be.false; + expect(registrars[0].fields.web).to.be.false; + expect(registrars[0].fields.legal).to.be.false; + expect(registrars[0].fields.riot).to.be.false; + expect(registrars[0].fields.email).to.be.false; + expect(registrars[0].fields.pgpFingerprint).to.be.false; + expect(registrars[0].fields.image).to.be.false; + expect(registrars[0].fields.twitter).to.be.false; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity11.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity11.ts new file mode 100644 index 00000000..d8d2d726 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity11.ts @@ -0,0 +1,95 @@ +/** + * Identity precompile tests - add sub + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, baltathar, charleth } from "@moonwall/util"; +import { decodeEventLog, toHex } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030311", + title: "Precompiles - Identity precompile - add sub", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "addSub", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [ + charleth.address, + { + hasData: true, + value: toHex("test"), + }, + ], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("SubIdentityAdded"); + expect(evmLog.args.sub).to.equal(charleth.address); + expect(evmLog.args.main).to.equal(baltathar.address); + }); + + it({ + id: "T01", + title: "should retrieve subs", + test: async function () { + const subs = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "subsOf", + args: [baltathar.address], + })) as any; + + expect(subs.deposit).to.equal(1005300000000000000n); + expect(subs.accounts).to.have.length(1); + expect(subs.accounts[0]).to.be.equal(charleth.address); + }, + }); + + it({ + id: "T02", + title: "should retrieve super", + test: async function () { + const superOf = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "superOf", + args: [charleth.address], + })) as any; + + expect(superOf.isValid).to.be.true; + expect(superOf.account).to.be.equal(baltathar.address); + expect(superOf.data.hasData).to.be.true; + expect(superOf.data.value).to.be.equal(toHex("test")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity12.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity12.ts new file mode 100644 index 00000000..f656e399 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity12.ts @@ -0,0 +1,87 @@ +/** + * Identity precompile tests - rename sub + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, baltathar, charleth } from "@moonwall/util"; +import { toHex } from "viem"; +import { PRECOMPILE_IDENTITY_ADDRESS, expectEVMResult } from "../../../../helpers"; + +describeSuite({ + id: "D030312", + title: "Precompiles - Identity precompile - rename sub", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar) + ); + await context.createBlock( + context + .polkadotJs() + .tx.identity.addSub(charleth.address, { Raw: "test" }) + .signAsync(baltathar) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "renameSub", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [ + charleth.address, + { + hasData: true, + value: toHex("foobar"), + }, + ], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + }); + + it({ + id: "T01", + title: "should retrieve subs", + test: async function () { + const subs = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "subsOf", + args: [baltathar.address], + })) as any; + + expect(subs.deposit).to.equal(1005300000000000000n); + expect(subs.accounts).to.have.length(1); + expect(subs.accounts[0]).to.be.equal(charleth.address); + }, + }); + + it({ + id: "T02", + title: "should retrieve super", + test: async function () { + const superOf = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "superOf", + args: [charleth.address], + })) as any; + + expect(superOf.isValid).to.be.true; + expect(superOf.account).to.be.equal(baltathar.address); + expect(superOf.data.hasData).to.be.true; + expect(superOf.data.value).to.be.equal(toHex("foobar")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity13.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity13.ts new file mode 100644 index 00000000..bf140c82 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity13.ts @@ -0,0 +1,76 @@ +/** + * Identity precompile tests - remove sub + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, baltathar, charleth } from "@moonwall/util"; +import { decodeEventLog } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030313", + title: "Precompiles - Identity precompile - remove sub", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar) + ); + await context.createBlock( + context + .polkadotJs() + .tx.identity.addSub(charleth.address, { Raw: "test" }) + .signAsync(baltathar) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "removeSub", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [charleth.address], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("SubIdentityRemoved"); + expect(evmLog.args.sub).to.equal(charleth.address); + expect(evmLog.args.main).to.equal(baltathar.address); + }); + + it({ + id: "T01", + title: "should have no subs", + test: async function () { + const subs = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "subsOf", + args: [baltathar.address], + })) as any; + + expect(subs.deposit).to.be.equal(0n); + expect(subs.accounts).to.be.empty; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity14.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity14.ts new file mode 100644 index 00000000..d2569605 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity14.ts @@ -0,0 +1,73 @@ +/** + * Identity precompile tests - quit sub + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { CHARLETH_PRIVATE_KEY, baltathar, charleth } from "@moonwall/util"; +import { decodeEventLog } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030314", + title: "Precompiles - Identity precompile - quit sub", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar) + ); + await context.createBlock( + context + .polkadotJs() + .tx.identity.addSub(charleth.address, { Raw: "test" }) + .signAsync(baltathar) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "quitSub", + privateKey: CHARLETH_PRIVATE_KEY, + rawTxOnly: true, + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("SubIdentityRevoked"); + expect(evmLog.args.sub).to.equal(charleth.address); + }); + + it({ + id: "T01", + title: "should have no super", + test: async function () { + const superOf = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "superOf", + args: [charleth.address], + })) as any; + + expect(superOf.isValid).to.be.false; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity2.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity2.ts new file mode 100644 index 00000000..97c2a795 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity2.ts @@ -0,0 +1,102 @@ +/** + * Identity precompile tests - set identity + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, baltathar } from "@moonwall/util"; +import { decodeEventLog, toHex } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030302", + title: "Precompiles - Identity precompile - set identity", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "setIdentity", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [ + { + additional: [ + { + key: { hasData: true, value: toHex("discord") }, + value: { hasData: true, value: toHex("my-discord") }, + }, + ], + display: { hasData: true, value: toHex("display") }, + legal: { hasData: true, value: toHex("legal") }, + web: { hasData: true, value: toHex("web") }, + riot: { hasData: true, value: toHex("riot") }, + email: { hasData: true, value: toHex("email") }, + hasPgpFingerprint: true, + pgpFingerprint: toHex(Uint8Array.from(new Array(20).fill(1))), + image: { hasData: true, value: toHex("image") }, + twitter: { hasData: true, value: toHex("twitter") }, + }, + ], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("IdentitySet"); + expect(evmLog.args.who).to.equal(baltathar.address); + }); + + it({ + id: "T01", + title: "should retrieve newly set identity", + test: async function () { + const identity = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "identity", + args: [baltathar.address], + })) as any; + + expect(identity.isValid).to.be.true; + expect(identity.judgements).to.be.empty; + expect(identity.deposit).to.equal(1034200000000000000n); + expect(identity.info.additional.length).to.equal(1); + expect(identity.info.additional[0].key.hasData).to.be.true; + expect(identity.info.additional[0].key.value).to.equal(toHex("discord")); + expect(identity.info.additional[0].value.hasData).to.be.true; + expect(identity.info.additional[0].value.value).to.equal(toHex("my-discord")); + expect(identity.info.display.hasData).to.be.true; + expect(identity.info.display.value).to.equal(toHex("display")); + expect(identity.info.legal.hasData).to.be.true; + expect(identity.info.legal.value).to.equal(toHex("legal")); + expect(identity.info.web.hasData).to.be.true; + expect(identity.info.web.value).to.equal(toHex("web")); + expect(identity.info.riot.hasData).to.be.true; + expect(identity.info.riot.value).to.equal(toHex("riot")); + expect(identity.info.email.hasData).to.be.true; + expect(identity.info.email.value).to.equal(toHex("email")); + expect(identity.info.hasPgpFingerprint).to.be.true; + expect(identity.info.pgpFingerprint).to.equal( + toHex(Uint8Array.from(new Array(20).fill(1))) + ); + expect(identity.info.image.hasData).to.be.true; + expect(identity.info.image.value).to.equal(toHex("image")); + expect(identity.info.twitter.hasData).to.be.true; + expect(identity.info.twitter.value).to.equal(toHex("twitter")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity3.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity3.ts new file mode 100644 index 00000000..7702797f --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity3.ts @@ -0,0 +1,67 @@ +/** + * Identity precompile tests - clear identity + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, baltathar } from "@moonwall/util"; +import { decodeEventLog } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030303", + title: "Precompiles - Identity precompile - clear identity", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock([ + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar), + ]); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "clearIdentity", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("IdentityCleared"); + expect(evmLog.args.who).to.equal(baltathar.address); + }); + + it({ + id: "T01", + title: "should have no identity", + test: async function () { + const identity = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "identity", + args: [baltathar.address], + })) as any; + + expect(identity.isValid).to.be.false; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity4.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity4.ts new file mode 100644 index 00000000..16f5db4a --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity4.ts @@ -0,0 +1,82 @@ +/** + * Identity precompile tests - request judgement + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, alith, baltathar } from "@moonwall/util"; +import { decodeEventLog, toHex } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030304", + title: "Precompiles - Identity precompile - request judgement", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + await context.createBlock([ + context.polkadotJs().tx.identity.setFee(0, 100n), + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar), + ]); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "requestJudgement", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [0, 100], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("JudgementRequested"); + expect(evmLog.args.who).to.equal(baltathar.address); + expect(evmLog.args.registrarIndex).to.equal(0); + }); + + it({ + id: "T01", + title: "should retrieve requested judgement as part of identity", + test: async function () { + const identity = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "identity", + args: [baltathar.address], + })) as any; + + expect(identity.isValid).to.be.true; + expect(identity.judgements).to.have.length(1); + expect(identity.judgements[0].registrarIndex).to.equal(0); + expect(identity.judgements[0].judgement.isFeePaid).to.be.true; + expect(identity.judgements[0].judgement.feePaidDeposit).to.equal(100n); + expect(identity.deposit).to.equal(1027400000000000000n); + expect(identity.info.display.hasData).to.be.true; + expect(identity.info.display.value).to.equal(toHex("display")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity5.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity5.ts new file mode 100644 index 00000000..5c10543b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity5.ts @@ -0,0 +1,82 @@ +/** + * Identity precompile tests - cancel requested judgement + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, alith, baltathar } from "@moonwall/util"; +import { decodeEventLog, toHex } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030305", + title: "Precompiles - Identity precompile - cancel requested judgement", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + await context.createBlock([ + context.polkadotJs().tx.identity.setFee(0, 100n), + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar), + ]); + await context.createBlock( + context.polkadotJs().tx.identity.requestJudgement(0, 1000n).signAsync(baltathar) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "cancelRequest", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [0], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("JudgementUnrequested"); + expect(evmLog.args.who).to.equal(baltathar.address); + expect(evmLog.args.registrarIndex).to.equal(0); + }); + + it({ + id: "T01", + title: "should have no requested judgement as part of identity", + test: async function () { + const identity = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "identity", + args: [baltathar.address], + })) as any; + + expect(identity.isValid).to.be.true; + expect(identity.judgements).to.be.empty; + expect(identity.deposit).to.equal(1027400000000000000n); + expect(identity.info.display.hasData).to.be.true; + expect(identity.info.display.value).to.equal(toHex("display")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity6.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity6.ts new file mode 100644 index 00000000..8591a33f --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity6.ts @@ -0,0 +1,98 @@ +/** + * Identity precompile tests - provide judgement + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { alith, baltathar } from "@moonwall/util"; +import { decodeEventLog, toHex } from "viem"; +import { + PRECOMPILE_IDENTITY_ADDRESS, + expectEVMResult, + expectSubstrateEvent, +} from "../../../../helpers"; + +describeSuite({ + id: "D030306", + title: "Precompiles - Identity precompile - provide judgement", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + const identityData = { + display: { raw: "display" }, + }; + await context.createBlock([ + context.polkadotJs().tx.identity.setFee(0, 100n), + context.polkadotJs().tx.identity.setIdentity(identityData).signAsync(baltathar), + ]); + await context.createBlock( + context.polkadotJs().tx.identity.requestJudgement(0, 1000n).signAsync(baltathar) + ); + + const identityHash = context + .polkadotJs() + .registry.createType("PalletIdentityLegacyIdentityInfo", identityData) + .hash.toHex(); + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "provideJudgement", + rawTxOnly: true, + args: [ + 0, + baltathar.address, + { + isUnknown: false, + isFeePaid: false, + feePaidDeposit: 0, + isReasonable: false, + isKnownGood: true, + isOutOfDate: false, + isLowQuality: false, + isErroneous: false, + }, + identityHash, + ], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: fetchCompiledContract("Identity").abi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + + expect(evmLog.eventName).to.equal("JudgementGiven"); + expect(evmLog.args.target).to.equal(baltathar.address); + expect(evmLog.args.registrarIndex).to.equal(0); + }); + + it({ + id: "T01", + title: "should have provided judgement as part of identity", + test: async function () { + const identity = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "identity", + args: [baltathar.address], + })) as any; + + expect(identity.isValid).to.be.true; + expect(identity.judgements).to.have.length(1); + expect(identity.judgements[0].judgement.isKnownGood).to.be.true; + expect(identity.deposit).to.equal(1027400000000000000n); + expect(identity.info.display.hasData).to.be.true; + expect(identity.info.display.value).to.equal(toHex("display")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity7.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity7.ts new file mode 100644 index 00000000..0675dbc1 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity7.ts @@ -0,0 +1,82 @@ +/** + * Identity precompile tests - set subs + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { BALTATHAR_PRIVATE_KEY, baltathar, charleth } from "@moonwall/util"; +import { toHex } from "viem"; +import { PRECOMPILE_IDENTITY_ADDRESS, expectEVMResult } from "../../../../helpers"; + +describeSuite({ + id: "D030307", + title: "Precompiles - Identity precompile - set subs", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.identity.setIdentity({ + display: { raw: "display" }, + }) + .signAsync(baltathar) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "setSubs", + privateKey: BALTATHAR_PRIVATE_KEY, + rawTxOnly: true, + args: [ + [ + { + account: charleth.address, + data: { hasData: true, value: toHex("test") }, + }, + ], + ], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + }); + + it({ + id: "T01", + title: "should retrieve subs", + test: async function () { + const subs = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "subsOf", + args: [baltathar.address], + })) as any; + + expect(subs.deposit).to.equal(1005300000000000000n); + expect(subs.accounts).to.have.length(1); + expect(subs.accounts[0]).to.be.equal(charleth.address); + }, + }); + + it({ + id: "T02", + title: "should retrieve super", + test: async function () { + const superOf = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "superOf", + args: [charleth.address], + })) as any; + + expect(superOf.isValid).to.be.true; + expect(superOf.account).to.be.equal(baltathar.address); + expect(superOf.data.hasData).to.be.true; + expect(superOf.data.value).to.be.equal(toHex("test")); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity8.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity8.ts new file mode 100644 index 00000000..549001a5 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity8.ts @@ -0,0 +1,61 @@ +/** + * Identity precompile tests - set fee + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { alith } from "@moonwall/util"; +import { expectEVMResult, PRECOMPILE_IDENTITY_ADDRESS } from "../../../../helpers"; + +describeSuite({ + id: "D030308", + title: "Precompiles - Identity precompile - set fee", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "setFee", + rawTxOnly: true, + args: [0, 100], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + }); + + it({ + id: "T01", + title: "should retrieve the registrar", + test: async function () { + const registrars = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "registrars", + })) as any; + + expect(registrars.length).to.equal(1); + expect(registrars[0].isValid).to.be.true; + expect(registrars[0].index).to.equal(0); + expect(registrars[0].account).to.equal(alith.address); + expect(registrars[0].fee).to.equal(100n); + expect(registrars[0].fields.display).to.be.false; + expect(registrars[0].fields.web).to.be.false; + expect(registrars[0].fields.legal).to.be.false; + expect(registrars[0].fields.riot).to.be.false; + expect(registrars[0].fields.email).to.be.false; + expect(registrars[0].fields.pgpFingerprint).to.be.false; + expect(registrars[0].fields.image).to.be.false; + expect(registrars[0].fields.twitter).to.be.false; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity9.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity9.ts new file mode 100644 index 00000000..fbfb4ce1 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-identity9.ts @@ -0,0 +1,73 @@ +/** + * Identity precompile tests - set fields + * Adapted from Moonbeam test suite + */ + +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { alith } from "@moonwall/util"; +import { expectEVMResult, PRECOMPILE_IDENTITY_ADDRESS } from "../../../../helpers"; + +describeSuite({ + id: "D030309", + title: "Precompiles - Identity precompile - set fields", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + beforeAll(async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.identity.addRegistrar(alith.address)) + ); + + const block = await context.createBlock( + await context.writeContract!({ + contractName: "Identity", + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + functionName: "setFields", + rawTxOnly: true, + args: [ + 0, + { + display: true, + web: true, + legal: true, + riot: true, + email: true, + pgpFingerprint: true, + image: true, + twitter: true, + }, + ], + }) + ); + + expectEVMResult(block.result!.events, "Succeed"); + }); + + it({ + id: "T01", + title: "should retrieve the registrar", + test: async function () { + const registrars = (await context.readContract!({ + contractAddress: PRECOMPILE_IDENTITY_ADDRESS, + contractName: "Identity", + functionName: "registrars", + })) as any; + + expect(registrars.length).to.equal(1); + expect(registrars[0].isValid).to.be.true; + expect(registrars[0].index).to.equal(0); + expect(registrars[0].account).to.equal(alith.address); + expect(registrars[0].fee).to.equal(0n); + expect(registrars[0].fields.display).to.be.true; + expect(registrars[0].fields.web).to.be.true; + expect(registrars[0].fields.legal).to.be.true; + expect(registrars[0].fields.riot).to.be.true; + expect(registrars[0].fields.email).to.be.true; + expect(registrars[0].fields.pgpFingerprint).to.be.true; + expect(registrars[0].fields.image).to.be.true; + expect(registrars[0].fields.twitter).to.be.true; + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-modexp.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-modexp.ts new file mode 100644 index 00000000..fe4e6d07 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-modexp.ts @@ -0,0 +1,824 @@ +import "@moonbeam-network/api-augment"; +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { EXTRINSIC_GAS_LIMIT, createViemTransaction } from "@moonwall/util"; +import { hexToU8a, u8aToHex } from "@polkadot/util"; +import { expectEVMResult, testVectors } from "../../../../helpers"; +import { calculateEIP7623Gas } from "../../../../helpers/fees"; + +const MODEXP_PRECOMPILE_ADDRESS = "0x0000000000000000000000000000000000000005"; + +// TODO: Gas tests (T03, T05-T21) are skipped because DataHaven uses Frontier stable2412 +// which doesn't include EIP-7623 gas calculation. Re-enable these tests after upgrading +// to Polkadot stable2506 (which includes the newer Frontier with EIP-7623 support). + +describeSuite({ + id: "D030108", + title: "Precompiles - modexp", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let hasherAddress: `0x${string}`; + + beforeAll(async function () { + const { contractAddress } = await context.deployContract!("HasherChecker"); + hasherAddress = contractAddress; + }); + + it({ + id: "T01", + title: "should be accessible from a smart contract", + test: async function () { + const rawTx = await context.writeContract!({ + contractName: "HasherChecker", + contractAddress: hasherAddress, + functionName: "modExpChecker", + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + }, + }); + + it({ + id: "T02", + title: "EIP example 1 - calculation", + test: async function () { + const rawTx = await context.writeContract!({ + contractName: "HasherChecker", + contractAddress: hasherAddress, + functionName: "modExpVerify", + args: [ + "3", + "115792089237316195423570985008687907853269984665640564039457584007908834671662", + "115792089237316195423570985008687907853269984665640564039457584007908834671663", + ], + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + + expect( + await context.readContract!({ + contractAddress: hasherAddress, + contractName: "HasherChecker", + functionName: "getResult", + }) + ).to.be.equals(1n); + }, + }); + + it({ + id: "T03", + title: "EIP example 1 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 3728n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000001" + // base length + "0000000000000000000000000000000000000000000000000000000000000020" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000020" + // modulus length + "03" + // base + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e" + // exponent + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"; // modulus + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T04", + title: "EIP example 2", + test: async function () { + await context.writeContract!({ + contractName: "HasherChecker", + contractAddress: hasherAddress, + functionName: "modExpVerify", + args: [ + "0", + "115792089237316195423570985008687907853269984665640564039457584007908834671662", + "115792089237316195423570985008687907853269984665640564039457584007908834671663", + ], + }); + + await context.createBlock(); + expect( + await context.readContract!({ + contractAddress: hasherAddress, + contractName: "HasherChecker", + functionName: "getResult", + }) + ).toBe(0n); + }, + }); + + it({ + id: "T05", + title: "EIP example 2 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 3728n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000000" + // base length + "0000000000000000000000000000000000000000000000000000000000000020" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000020" + // modulus length + // base length is zero so value is inferred zero + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e" + // exponent + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"; // modulus + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T06", + title: "nagydani-1-square - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 1869n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000040" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000040" + // modulus length + testVectors["nagydani-1-square"].base + + testVectors["nagydani-1-square"].exponent + + testVectors["nagydani-1-square"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T07", + title: "nagydani-1-qube - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 1869n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000040" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000040" + // modulus length + testVectors["nagydani-1-square"].base + + testVectors["nagydani-1-qube"].exponent + + testVectors["nagydani-1-qube"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T08", + title: "nagydani-1-pow0x10001 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 2010n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000040" + // base length + "0000000000000000000000000000000000000000000000000000000000000003" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000040" + // modulus length + testVectors["nagydani-1-pow0x10001"].base + + testVectors["nagydani-1-pow0x10001"].exponent + + testVectors["nagydani-1-pow0x10001"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T09", + title: "nagydani-2-square - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 1869n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000080" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000080" + // modulus length + testVectors["nagydani-2-square"].base + + testVectors["nagydani-2-square"].exponent + + testVectors["nagydani-2-square"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T10", + title: "nagydani-2-qube - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 1869n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000080" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000080" + // modulus length + testVectors["nagydani-2-qube"].base + + testVectors["nagydani-2-qube"].exponent + + testVectors["nagydani-2-qube"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T11", + title: "nagydani-2-pow0x10001 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 3034n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000080" + // base length + "0000000000000000000000000000000000000000000000000000000000000003" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000080" + // modulus length + testVectors["nagydani-2-pow0x10001"].base + + testVectors["nagydani-2-pow0x10001"].exponent + + testVectors["nagydani-2-pow0x10001"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T12", + title: "nagydani-3-square - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 2010n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000100" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000100" + // modulus length + testVectors["nagydani-3-square"].base + + testVectors["nagydani-3-square"].exponent + + testVectors["nagydani-3-square"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T13", + title: "nagydani-3-qube - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 2010n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000100" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000100" + // modulus length + testVectors["nagydani-3-qube"].base + + testVectors["nagydani-3-qube"].exponent + + testVectors["nagydani-3-qube"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T14", + title: "nagydani-3-pow0x10001 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 7130n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000100" + // base length + "0000000000000000000000000000000000000000000000000000000000000003" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000100" + // modulus length + testVectors["nagydani-3-pow0x10001"].base + + testVectors["nagydani-3-pow0x10001"].exponent + + testVectors["nagydani-3-pow0x10001"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T15", + title: "nagydani-4-square - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 3034n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000200" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000200" + // modulus length + testVectors["nagydani-4-square"].base + + testVectors["nagydani-4-square"].exponent + + testVectors["nagydani-4-square"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T16", + title: "nagydani-4-qube - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 3034n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000200" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000200" + // modulus length + testVectors["nagydani-4-qube"].base + + testVectors["nagydani-4-qube"].exponent + + testVectors["nagydani-4-qube"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T17", + title: "nagydani-4-pow0x10001 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 23514n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000200" + // base length + "0000000000000000000000000000000000000000000000000000000000000003" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000200" + // modulus length + testVectors["nagydani-4-pow0x10001"].base + + testVectors["nagydani-4-pow0x10001"].exponent + + testVectors["nagydani-4-pow0x10001"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T18", + title: "nagydani-5-square - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 7130n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000400" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000400" + // modulus length + testVectors["nagydani-5-square"].base + + testVectors["nagydani-5-square"].exponent + + testVectors["nagydani-5-square"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T19", + title: "nagydani-5-qube - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 7130n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000400" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000400" + // modulus length + testVectors["nagydani-5-qube"].base + + testVectors["nagydani-5-qube"].exponent + + testVectors["nagydani-5-qube"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T20", + title: "nagydani-5-pow0x10001 - gas", + modifier: "skip", + test: async function () { + const expectedModExpGasCost = 89749n; + const inputData = + "0000000000000000000000000000000000000000000000000000000000000400" + // base length + "0000000000000000000000000000000000000000000000000000000000000003" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000400" + // modulus length + testVectors["nagydani-5-pow0x10001"].base + + testVectors["nagydani-5-pow0x10001"].exponent + + testVectors["nagydani-5-pow0x10001"].modulus; + const byteArray = hexToU8a(inputData); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T21", + title: "Exponent > 32", + modifier: "skip", + test: async function () { + // We multiply by a factor of 20 for an even mod. + // See https://github.com/paritytech/frontier/pull/1017 + const expectedModExpGasCost = 7104n * 20n; + const byteArray = new Uint8Array([ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x02, 0x0, 0x0, + 0xb3, 0x0, 0x0, 0x02, 0x0, 0x0, 0x7a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xfb, 0x0, 0x0, 0x0, 0x0, 0x04, 0x26, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 96, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0x02, 0x0, 0x0, 0xb3, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf9, + ]); + const inputData = u8aToHex(byteArray); + const inputLength = byteArray.length; + const numZeroBytes = byteArray.filter((a) => a === 0).length; + const numNonZeroBytes = inputLength - numZeroBytes; + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: inputData, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + const isPrecompileCheckGas = 2368n; + const expectedGasUsed = calculateEIP7623Gas( + numZeroBytes, + numNonZeroBytes, + expectedModExpGasCost + isPrecompileCheckGas + ); + expect(receipt.gasUsed, "ModExp gas pricing mismatch").to.equal(expectedGasUsed); + }, + }); + + it({ + id: "T22", + title: "should pad input when too short", + test: async function () { + const inputData = + "0000000000000000000000000000000000000000000000000000000000000001" + // base length + "0000000000000000000000000000000000000000000000000000000000000001" + // exponent length + "0000000000000000000000000000000000000000000000000000000000000002" + // modulus length + "05" + // base + "03" + // exponent + "01"; // modulus + + const rawTxn = await createViemTransaction(context, { + to: MODEXP_PRECOMPILE_ADDRESS, + data: ("0x" + inputData) as `0x${string}`, + gas: EXTRINSIC_GAS_LIMIT, + }); + const { result } = await context.createBlock(rawTxn); + + const receipt = await context + .viem() + .getTransactionReceipt({ hash: result!.hash as `0x${string}` }); + expect(receipt.status).toBe("success"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-preimage.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-preimage.ts new file mode 100644 index 00000000..7e6cb95d --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-preimage.ts @@ -0,0 +1,106 @@ +import "@moonbeam-network/api-augment"; +import { beforeAll, beforeEach, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { type Abi, decodeEventLog } from "viem"; +import { Preimage, expectEVMResult, expectSubstrateEvent } from "../../../../helpers"; + +// Each test is instantiating a new proposal (Not ideal for isolation but easier to write) +// Be careful to not reach the maximum number of proposals. +describeSuite({ + id: "D030501", + title: "Precompiles - Preimage precompile", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + let PreimageAbi: Abi; + let preimage: Preimage; + + beforeAll(async function () { + const { abi } = fetchCompiledContract("Preimage"); + PreimageAbi = abi; + }); + + beforeEach(async function () { + preimage = new Preimage(context); + }); + + it({ + id: "T01", + title: "should allow to note Preimage", + test: async function () { + const call = context.polkadotJs().tx.identity.setIdentity({ display: { raw: "Me" } }); + const block = await preimage.notePreimage(call.toHex()).block(); + + // Verifies the EVM Side + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: PreimageAbi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + expect(evmLog.eventName, "Wrong event").to.equal("PreimageNoted"); + expect(evmLog.args.hash).to.equal(call.hash.toHex()); + + // Verifies the Substrate side + const preImage = await context + .polkadotJs() + .query.preimage.preimageFor([call.hash.toHex(), 15]); + expect(preImage.unwrap().toHex()).to.equal(call.toHex()); + }, + }); + + it({ + id: "T02", + title: "should allow to unnote a Preimage", + test: async function () { + const call = context.polkadotJs().tx.identity.setIdentity({ display: { raw: "You" } }); + await preimage.notePreimage(call.toHex()).block(); + const block = await preimage.unnotePreimage(call.hash.toHex()).block(); + + // Verifies the EVM Side + expectEVMResult(block.result!.events, "Succeed"); + const { data } = expectSubstrateEvent(block, "evm", "Log"); + const evmLog = decodeEventLog({ + abi: PreimageAbi, + topics: data[0].topics.map((t) => t.toHex()) as any, + data: data[0].data.toHex(), + }) as any; + // context.readPrecompile!({functionName}) + expect(evmLog.eventName, "Wrong event").to.equal("PreimageUnnoted"); + expect(evmLog.args.hash).to.equal(call.hash.toHex()); + + // Verifies the Substrate side + const preImage = await context + .polkadotJs() + .query.preimage.preimageFor([call.hash.toHex(), 1000]); + expect(preImage.isNone).to.equal(true); + }, + }); + + it({ + id: "T03", + title: "should fail to note the same Preimage twice", + test: async function () { + const call = context.polkadotJs().tx.identity.setIdentity({ display: { raw: "Repeated" } }); + await preimage.notePreimage(call.toHex()).block(); + await expect( + async () => await preimage.notePreimage(call.toHex()).block(), + "Transaction should be reverted but instead preimage noted" + ).rejects.toThrowError("AlreadyNoted"); + }, + }); + + it({ + id: "T04", + title: "should fail to unnote a missing Preimage", + test: async function () { + const call = context + .polkadotJs() + .tx.identity.setIdentity({ display: { raw: "Missing Preimage" } }); + await expect( + async () => await preimage.unnotePreimage(call.hash.toHex()).block(), + "Transaction should be reverted but instead preimage unnoted" + ).rejects.toThrowError("NotNoted"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-proxy.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-proxy.ts new file mode 100644 index 00000000..62c39bb0 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-proxy.ts @@ -0,0 +1,544 @@ +/** + * Proxy precompile tests + * Tests the Proxy precompile API for managing proxy accounts via EVM + */ + +import { describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + BALTATHAR_ADDRESS, + BALTATHAR_PRIVATE_KEY, + CHARLETH_ADDRESS, + CHARLETH_PRIVATE_KEY, + createViemTransaction, + sendRawTransaction, +} from "@moonwall/util"; +import { encodeFunctionData } from "viem"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { expectEVMResult, PRECOMPILE_PROXY_ADDRESS } from "../../../../helpers"; + +// Proxy type constants (matching Substrate proxy types from Proxy.sol) +const CONTRACT_PROXY_TYPE_ANY = 0; +const CONTRACT_PROXY_TYPE_NON_TRANSFER = 1; +const CONTRACT_PROXY_TYPE_GOVERNANCE = 2; +const CONTRACT_PROXY_TYPE_STAKING = 3; +const CONTRACT_PROXY_TYPE_CANCEL_PROXY = 4; +const CONTRACT_PROXY_TYPE_BALANCES = 5; + +// Invalid proxy type for testing error handling +const CONTRACT_PROXY_TYPE_INVALID = 99; + +describeSuite({ + id: "D030601", + title: "Precompile - Proxy", + foundationMethods: "dev", + testCases: ({ it, log, context }) => { + it({ + id: "T01", + title: "should succeed adding a proxy", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + + // Verify proxy was added via substrate + const proxies = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + const hasProxy = proxies[0].some( + (p: any) => + p.delegate.toString() === randomAccount && p.proxyType.toString() === "Staking" + ); + expect(hasProxy).to.be.true; + }, + }); + + it({ + id: "T02", + title: "should fail re-adding the same proxy", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + // First add + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + await context.createBlock(rawTx); + + // Second add should fail with exact error message + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + }) + ).rejects.toThrowError("Cannot add more than one proxy"); + }, + }); + + it({ + id: "T03", + title: "should fail removing non-existent proxy", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "removeProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + }) + ).rejects.toThrowError(/NotFound/i); + }, + }); + + it({ + id: "T04", + title: "should succeed removing an existing proxy", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + // Add proxy + const addTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + await context.createBlock(addTx); + + // Remove proxy + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "removeProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + + // Verify proxy was removed + const proxies = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + const hasProxy = proxies[0].some((p: any) => p.delegate.toString() === randomAccount); + expect(hasProxy).to.be.false; + }, + }); + + it({ + id: "T05", + title: "should succeed removing all proxies", + test: async () => { + // First ensure no proxies exist + const proxiesInitial = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + if (proxiesInitial[0].length > 0) { + const clearTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "removeProxies", + rawTxOnly: true, + }); + await context.createBlock(clearTx); + } + + // Add exactly two proxies + const account1 = privateKeyToAccount(generatePrivateKey()).address; + const account2 = privateKeyToAccount(generatePrivateKey()).address; + + const addTx1 = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [account1, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + await context.createBlock(addTx1); + + const addTx2 = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [account2, CONTRACT_PROXY_TYPE_GOVERNANCE, 0], + rawTxOnly: true, + }); + await context.createBlock(addTx2); + + const proxiesBefore = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + expect(proxiesBefore[0].length).toBe(2); + + // Remove all proxies + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "removeProxies", + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + + const proxiesAfter = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + expect(proxiesAfter[0].length).toBe(0); + }, + }); + + it({ + id: "T06", + title: "should correctly report proxy status via isProxy", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + // Check isProxy returns false before adding any proxy + const isProxyBefore = await context.readContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "isProxy", + args: [ALITH_ADDRESS, randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + }); + expect(isProxyBefore).to.be.false; + + // Add proxy + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + await context.createBlock(rawTx); + + // Check isProxy returns true for correct parameters + const isProxy = await context.readContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "isProxy", + args: [ALITH_ADDRESS, randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + }); + expect(isProxy).to.be.true; + + // Check isProxy returns false for wrong type + const isProxyWrongType = await context.readContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "isProxy", + args: [ALITH_ADDRESS, randomAccount, CONTRACT_PROXY_TYPE_ANY, 0], + }); + expect(isProxyWrongType).to.be.false; + + // Check isProxy returns false for wrong delay + const isProxyWrongDelay = await context.readContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "isProxy", + args: [ALITH_ADDRESS, randomAccount, CONTRACT_PROXY_TYPE_STAKING, 2], + }); + expect(isProxyWrongDelay).to.be.false; + }, + }); + + it({ + id: "T07", + title: "should reject proxy call from non-proxy account", + test: async () => { + // BALTATHAR tries to make a proxy call on behalf of ALITH without being a proxy + const { abi } = fetchCompiledContract("Proxy"); + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "proxy", + args: [ALITH_ADDRESS, CHARLETH_ADDRESS, "0x00"], + privateKey: BALTATHAR_PRIVATE_KEY, + }) + ).rejects.toThrowError("Not proxy"); + }, + }); + + it({ + id: "T08", + title: "should allow proxy call from valid proxy account", + test: async () => { + const privateKey = generatePrivateKey(); + const randomAccount = privateKeyToAccount(privateKey).address; + + // Add BALTATHAR as proxy for ALITH with Any type + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [BALTATHAR_ADDRESS, CONTRACT_PROXY_TYPE_ANY, 0], + rawTxOnly: true, + }); + await context.createBlock(rawTx); + + // Use BALTATHAR to transfer value on behalf of ALITH + const { abi } = fetchCompiledContract("Proxy"); + const proxyTx = await createViemTransaction(context, { + to: PRECOMPILE_PROXY_ADDRESS, + privateKey: BALTATHAR_PRIVATE_KEY, + value: 1000n, + data: encodeFunctionData({ + abi, + functionName: "proxy", + args: [ALITH_ADDRESS, randomAccount, "0x00"], + }), + }); + const txHash = (await sendRawTransaction(context, proxyTx)) as `0x${string}`; + + // Create two blocks to ensure the transaction is included + await context.createBlock(); + await context.createBlock(); + + const receipt = await context.viem().getTransactionReceipt({ hash: txHash }); + expect(receipt.status).toBe("success"); + + // Verify transfer happened + expect(await context.viem().getBalance({ address: randomAccount })).toBe(1000n); + }, + }); + + it({ + id: "T09", + title: "should succeed with proxyForceType for matching proxy type", + test: async () => { + const privateKey = generatePrivateKey(); + const randomAccount = privateKeyToAccount(privateKey).address; + + // Add CHARLETH as Balances proxy for ALITH + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [CHARLETH_ADDRESS, CONTRACT_PROXY_TYPE_BALANCES, 0], + rawTxOnly: true, + }); + await context.createBlock(rawTx); + + // Use CHARLETH to transfer value on behalf of ALITH using proxyForceType + const { abi } = fetchCompiledContract("Proxy"); + const proxyTx = await createViemTransaction(context, { + to: PRECOMPILE_PROXY_ADDRESS, + privateKey: CHARLETH_PRIVATE_KEY, + value: 500n, + data: encodeFunctionData({ + abi, + functionName: "proxyForceType", + args: [ALITH_ADDRESS, CONTRACT_PROXY_TYPE_BALANCES, randomAccount, "0x00"], + }), + }); + const { result } = await context.createBlock(proxyTx); + expectEVMResult(result!.events, "Succeed"); + + // Verify transfer happened + expect(await context.viem().getBalance({ address: randomAccount })).toBe(500n); + }, + }); + + it({ + id: "T10", + title: "should fail proxyForceType with mismatched proxy type", + test: async () => { + // CHARLETH is a Balances proxy for ALITH (from T09 or set up here) + const proxies = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + const hasBalancesProxy = proxies[0].some( + (p: any) => + p.delegate.toString() === CHARLETH_ADDRESS && p.proxyType.toString() === "Balances" + ); + + if (!hasBalancesProxy) { + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [CHARLETH_ADDRESS, CONTRACT_PROXY_TYPE_BALANCES, 0], + rawTxOnly: true, + }); + await context.createBlock(rawTx); + } + + // Try to use proxyForceType with Governance type (CHARLETH only has Balances) + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "proxyForceType", + args: [ALITH_ADDRESS, CONTRACT_PROXY_TYPE_GOVERNANCE, BALTATHAR_ADDRESS, "0x00"], + privateKey: CHARLETH_PRIVATE_KEY, + }) + ).rejects.toThrowError(/Not proxy/i); + }, + }); + + it({ + id: "T11", + title: "should fail addProxy with invalid proxy type value", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_INVALID, 0], + }) + ).rejects.toThrowError(/Failed decoding value to ProxyType/i); + }, + }); + + it({ + id: "T12", + title: "should succeed removeProxies when no proxies exist", + test: async () => { + // Use a fresh account that has no proxies + const privateKey = generatePrivateKey(); + const freshAccount = privateKeyToAccount(privateKey); + + // Fund the fresh account so it can make transactions + const fundTx = await createViemTransaction(context, { + to: freshAccount.address, + value: 10n * 10n ** 18n, // 10 tokens + }); + await context.createBlock(fundTx); + + // Verify no proxies exist for this account + const proxiesBefore = await context + .polkadotJs() + .query.proxy.proxies(freshAccount.address); + expect(proxiesBefore[0].length).toBe(0); + + // removeProxies should succeed even with no proxies + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "removeProxies", + privateKey: privateKey, + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + }, + }); + + it({ + id: "T13", + title: "should correctly handle non-zero delay proxy", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + const delay = 5; + + // Add proxy with non-zero delay + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, delay], + rawTxOnly: true, + }); + const { result } = await context.createBlock(rawTx); + expectEVMResult(result!.events, "Succeed"); + + // Verify proxy was added with correct delay via substrate + const proxies = await context.polkadotJs().query.proxy.proxies(ALITH_ADDRESS); + const proxyEntry = proxies[0].find( + (p: any) => + p.delegate.toString() === randomAccount && p.proxyType.toString() === "Staking" + ); + expect(proxyEntry).toBeDefined(); + expect(proxyEntry.delay.toNumber()).toBe(delay); + + // isProxy should return true with correct delay + const isProxyCorrectDelay = await context.readContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "isProxy", + args: [ALITH_ADDRESS, randomAccount, CONTRACT_PROXY_TYPE_STAKING, delay], + }); + expect(isProxyCorrectDelay).to.be.true; + + // isProxy should return false with wrong delay (0) + const isProxyWrongDelay = await context.readContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "isProxy", + args: [ALITH_ADDRESS, randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + }); + expect(isProxyWrongDelay).to.be.false; + }, + }); + + it({ + id: "T14", + title: "should fail proxyForceType with invalid proxy type value", + test: async () => { + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "proxyForceType", + args: [ALITH_ADDRESS, CONTRACT_PROXY_TYPE_INVALID, CHARLETH_ADDRESS, "0x00"], + privateKey: BALTATHAR_PRIVATE_KEY, + }) + ).rejects.toThrowError(/Failed decoding value to ProxyType/i); + }, + }); + + it({ + id: "T15", + title: "should fail adding proxy with different type for same delegate", + test: async () => { + const randomAccount = privateKeyToAccount(generatePrivateKey()).address; + + // First add with Staking type + const rawTx = await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_STAKING, 0], + rawTxOnly: true, + }); + await context.createBlock(rawTx); + + // Try to add same delegate with different type (Any - more permissive) + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_ANY, 0], + }) + ).rejects.toThrowError("Cannot add more than one proxy"); + + // Try to add same delegate with different type (Governance - less permissive) + await expect( + async () => + await context.writeContract!({ + contractAddress: PRECOMPILE_PROXY_ADDRESS, + contractName: "Proxy", + functionName: "addProxy", + args: [randomAccount, CONTRACT_PROXY_TYPE_GOVERNANCE, 0], + }) + ).rejects.toThrowError("Cannot add more than one proxy"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-ripemd160.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-ripemd160.ts new file mode 100644 index 00000000..05167d35 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-ripemd160.ts @@ -0,0 +1,50 @@ +/** + * RIPEMD-160 precompile tests + * Adapted from Moonbeam test suite + */ + +import { describeSuite, expect } from "@moonwall/cli"; +import { toHex } from "viem"; +import { expectEVMResult } from "../../../../helpers"; + +describeSuite({ + id: "D030105", + title: "Precompiles - ripemd160", + foundationMethods: "dev", + testCases: ({ context, log, it }) => { + it({ + id: "T01", + title: "should be valid", + test: async function () { + expect( + ( + await context.viem().call({ + to: "0x0000000000000000000000000000000000000003", + data: toHex("Hello world!"), + }) + ).data + ).equals("0x0000000000000000000000007f772647d88750add82d8e1a7a3e5c0902a346a3"); + }, + }); + + it({ + id: "T02", + title: "should be accessible from a smart contract", + test: async function () { + const { contractAddress } = await context.deployContract!("HasherChecker"); + + // Execute the contract ripemd160 call + const rawTxn = await context.writeContract!({ + contractAddress, + contractName: "HasherChecker", + functionName: "ripemd160Check", + rawTxOnly: true, + }); + + const { result } = await context.createBlock(rawTxn); + + expectEVMResult(result!.events, "Succeed"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/precompile/test-precompile-sha3fips.ts b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-sha3fips.ts new file mode 100644 index 00000000..c98efe96 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/precompile/test-precompile-sha3fips.ts @@ -0,0 +1,30 @@ +/** + * SHA3-FIPS precompile tests + * Adapted from Moonbeam test suite + */ + +import { describeSuite, expect } from "@moonwall/cli"; + +describeSuite({ + id: "D030106", + title: "Precompiles - sha3fips", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + // Test taken from https://github.com/binance-chain/bsc/pull/118 + it({ + id: "T01", + title: "sha3fips should be valid", + test: async function () { + expect( + ( + await context.viem().call({ + to: "0x0000000000000000000000000000000000000400", + data: ("0x0448250ebe88d77e0a12bcf530fe6a2cf1ac176945638d309b840d631940c93b78c2bd" + + "6d16f227a8877e3f1604cd75b9c5a8ab0cac95174a8a0a0f8ea9e4c10bca") as `0x${string}`, + }) + ).data + ).equals("0xc7647f7e251bf1bd70863c8693e93a4e77dd0c9a689073e987d51254317dc704"); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/proxy/test-proxy.ts b/test/moonwall/suites/dev/stagenet/proxy/test-proxy.ts new file mode 100644 index 00000000..5c313bef --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/proxy/test-proxy.ts @@ -0,0 +1,257 @@ +import { beforeEach, describeSuite, expect } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + CHARLETH_ADDRESS, + type KeyringPair, + alith, + generateKeyringPair, +} from "@moonwall/util"; + +// In these tests Alith will allow signer to perform calls on her behalf. +// Charleth is used as a target account when making transfers. + +describeSuite({ + id: "D022902", + title: "Proxy - proxy", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let signer: KeyringPair; + + beforeEach(async () => { + signer = generateKeyringPair("ethereum"); + + await context.createBlock( + context.polkadotJs().tx.balances.transferAllowDeath(signer.address, 5n * 10n ** 18n) + ); + }); + + it({ + id: "T01", + title: "shouldn't accept unknown proxy", + test: async function () { + const beforeCharlethBalance = await context + .viem() + .getBalance({ address: CHARLETH_ADDRESS }); + + const expectEvents = [context.polkadotJs().events.system.ExtrinsicFailed]; + + await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxy( + ALITH_ADDRESS, + null, + context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100) + ) + .signAsync(signer), + { expectEvents, signer: alith, allowFailures: true } + ); + const afterCharlethBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlethBalance - beforeCharlethBalance).to.be.eq(0n); + }, + }); + + it({ + id: "T02", + title: "should accept known proxy", + test: async () => { + const beforeCharlethBalance = await context + .viem() + .getBalance({ address: CHARLETH_ADDRESS }); + + const events1 = [ + context.polkadotJs().events.system.ExtrinsicSuccess, + context.polkadotJs().events.proxy.ProxyAdded, + ]; + + const { result } = await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(signer.address, "Any", 0), + { signer: alith, expectEvents: events1 } + ); + const proxyAdded = result?.events.find(({ event }) => + context.polkadotJs().events.proxy.ProxyAdded.is(event) + ); + expect(proxyAdded).to.not.be.undefined; + expect(proxyAdded!.event.data[2].toString()).to.be.eq("Any"); //ProxyType + + const events2 = [ + context.polkadotJs().events.system.ExtrinsicSuccess, + context.polkadotJs().events.proxy.ProxyExecuted, + ]; + + const { result: result2 } = await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxy( + alith.address, + null, + context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100) + ) + .signAsync(signer), + { signer: alith, expectEvents: events2 } + ); + const proxyExecuted = result2?.events.find(({ event }) => + context.polkadotJs().events.proxy.ProxyExecuted.is(event) + ); + expect(proxyExecuted).to.not.be.undefined; + expect(proxyExecuted!.event.data[0].toString()).to.be.eq("Ok"); + const afterCharlethBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlethBalance - beforeCharlethBalance).to.be.eq(100n); + }, + }); + + it({ + id: "T03", + title: "shouldn't accept removed proxy", + test: async () => { + const beforeCharlethBalance = await context + .viem() + .getBalance({ address: CHARLETH_ADDRESS }); + + await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(signer.address, "Any", 0), + { signer: alith, allowFailures: false } + ); + + await context.createBlock( + context.polkadotJs().tx.proxy.removeProxy(signer.address, "Any", 0), + { signer: alith, allowFailures: false } + ); + + await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxy( + alith.address, + null, + context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100) + ) + .signAsync(signer), + { signer: alith, expectEvents: [context.polkadotJs().events.system.ExtrinsicFailed] } + ); + const afterCharlethBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlethBalance - beforeCharlethBalance).to.be.eq(0n); + }, + }); + + it({ + id: "T04", + title: "shouldn't accept instant for delayed proxy", + test: async () => { + const beforeCharlethBalance = await context + .viem() + .getBalance({ address: CHARLETH_ADDRESS }); + + await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(signer.address, "Any", 2), + { signer: alith, allowFailures: false } + ); + + await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxy( + alith.address, + null, + context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100) + ) + .signAsync(signer), + { signer: alith, expectEvents: [context.polkadotJs().events.system.ExtrinsicFailed] } + ); + const afterCharlethBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlethBalance - beforeCharlethBalance).to.be.eq(0n); + }, + }); + + it({ + id: "T05", + title: "shouldn't accept early delayed proxy", + test: async () => { + const beforeCharlethBalance = await context + .viem() + .getBalance({ address: CHARLETH_ADDRESS }); + const { result } = await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(signer.address, "Any", 6), + { signer: alith, allowFailures: false } + ); + result?.events.forEach(({ event }) => log(`1${event.method}(${event.data})`)); + + const transfer = context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100); + + const { result: result2 } = await context.createBlock( + context.polkadotJs().tx.proxy.announce(alith.address, transfer.hash).signAsync(signer), + { + signer: alith, + expectEvents: [context.polkadotJs().events.proxy.Announced], + allowFailures: false, + } + ); + result2?.events.forEach(({ event }) => log(`2${event.method}(${event.data})`)); + + const { result: result3 } = await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxyAnnounced(signer.address, alith.address, null, transfer) + .signAsync(signer), + { + signer: alith, + expectEvents: [context.polkadotJs().events.system.ExtrinsicFailed], + } + ); + result3?.events.forEach(({ event }) => log(`3${event.method}(${event.data})`)); + const afterCharlethBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlethBalance - beforeCharlethBalance).to.be.eq(0n); + }, + }); + + it({ + id: "T06", + title: "should accept on-time delayed proxy ", + test: async () => { + const beforeCharlethBalance = await context + .viem() + .getBalance({ address: CHARLETH_ADDRESS }); + await context.createBlock( + context.polkadotJs().tx.proxy.addProxy(signer.address, "Any", 2), + { signer: alith, allowFailures: false } + ); + + const transfer = context.polkadotJs().tx.balances.transferAllowDeath(CHARLETH_ADDRESS, 100); + const u8a = transfer.method.toU8a(); + const transfer_hash = transfer.registry.hash(u8a).toHex(); + + const { result: result2 } = await context.createBlock( + context.polkadotJs().tx.proxy.announce(alith.address, transfer_hash).signAsync(signer), + { + signer: alith, + expectEvents: [context.polkadotJs().events.proxy.Announced], + allowFailures: false, + } + ); + const announced = result2?.events.find(({ event }) => + context.polkadotJs().events.proxy.Announced.is(event) + ); + expect(announced).to.not.be.undefined; + expect(announced!.event.data[2].toHex()).to.eq(transfer_hash); + + await context.createBlock(); + await context.createBlock(); + + // On time. + const { result: result3 } = await context.createBlock( + context + .polkadotJs() + .tx.proxy.proxyAnnounced(signer.address, alith.address, null, transfer) + .signAsync(signer), + { + signer: alith, + expectEvents: [context.polkadotJs().events.proxy.ProxyExecuted], + allowFailures: false, + } + ); + const afterCharlethBalance = await context.viem().getBalance({ address: CHARLETH_ADDRESS }); + expect(afterCharlethBalance - beforeCharlethBalance).to.be.eq(100n); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/receipt/test-receipt-revert.ts b/test/moonwall/suites/dev/stagenet/receipt/test-receipt-revert.ts new file mode 100644 index 00000000..37890c0d --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/receipt/test-receipt-revert.ts @@ -0,0 +1,33 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { getAddress } from "viem"; + +describeSuite({ + id: "D023101", + title: "Receipt - Revert", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should generate a receipt for a reverted transaction", + test: async function () { + const { hash } = await context.deployContract!("FailingConstructor", { gas: 300000n }); + const receipt = await context.viem().getTransactionReceipt({ hash }); + + expect(receipt.status).toBe("reverted"); + expect(receipt.blockNumber).toBe(1n); + expect(getAddress(receipt.contractAddress!)).toBe( + getAddress("0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3") + ); + expect(receipt.cumulativeGasUsed).toBe(54604n); + expect(getAddress(receipt.from!)).toBe( + getAddress("0xf24ff3a9cf04c71dbc94d0b566f7a27b94566cac") + ); + expect(receipt.gasUsed).toBe(54604n); + expect(receipt.logs).toStrictEqual([]); + expect(receipt.transactionHash).toBe(hash); + expect(receipt.to).toBe(null); + expect(receipt.transactionIndex).toBe(0); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/receipt/test-receipt.ts b/test/moonwall/suites/dev/stagenet/receipt/test-receipt.ts new file mode 100644 index 00000000..130e70d4 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/receipt/test-receipt.ts @@ -0,0 +1,61 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { BALTATHAR_ADDRESS, alith } from "@moonwall/util"; + +describeSuite({ + id: "D023103", + title: "Receipt - Contract", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let txHash: string; + let eventContract: `0x${string}`; + + beforeAll(async () => { + const { contractAddress, hash } = await context.deployContract!("EventEmitter"); + eventContract = contractAddress; + txHash = hash; + }); + + it({ + id: "T01", + title: "Should generate receipt", + test: async function () { + const block = await context.viem().getBlock({ blockNumber: 1n }); + const receipt = await context + .viem() + .getTransactionReceipt({ hash: txHash as `0x${string}` }); + + expect(receipt.blockHash).toBe(block.hash); + expect(receipt.blockNumber).toBe(block.number); + expect(receipt.from).toBe(alith.address.toLowerCase()); + expect(receipt.logs.length).toBe(1); + expect(receipt.logs[0].address).toBe(eventContract); + expect(receipt.logs[0].blockHash).toBe(block.hash); + }, + }); + + it({ + id: "T02", + title: "should calculate effective gas price", + test: async function () { + const maxFeePerGas = 10_000_000_000n * 2n; + + const rawTxn = await context.createTxn!({ + gas: 21000n, + libraryType: "viem", + maxFeePerGas: maxFeePerGas, + maxPriorityFeePerGas: maxFeePerGas, + to: BALTATHAR_ADDRESS, + data: "0x", + txnType: "eip1559", + }); + await context.createBlock(rawTxn); + + const block = await context.viem().getBlock(); + const receipt = await context + .viem() + .getTransactionReceipt({ hash: block.transactions[0] as `0x${string}` }); + expect(receipt.effectiveGasPrice).to.be.eq(maxFeePerGas); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/storage-growth/test-evm-store-storage-growth.ts b/test/moonwall/suites/dev/stagenet/storage-growth/test-evm-store-storage-growth.ts new file mode 100644 index 00000000..964dd79f --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/storage-growth/test-evm-store-storage-growth.ts @@ -0,0 +1,76 @@ +// TODO: Constants (storage growth ratios, limits) may need adjustment for DataHaven's runtime configuration +import { + TransactionTypes, + beforeAll, + deployCreateCompiledContract, + describeSuite, +} from "@moonwall/cli"; +import { createEthersTransaction } from "@moonwall/util"; +import { expectEVMResult, expectOk } from "../../../../helpers"; +import { type Abi, encodeFunctionData } from "viem"; + +describeSuite({ + id: "D023403", + title: "Storage growth limit - New Entries", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let storageLoopAddress: `0x${string}`; + let storageLoopAbi: Abi; + // Number of bytes added to storage for a new entry. + const ACCOUNT_STORAGE_SIZE = 116; + // Ratio of gas to storage growth. (BlockGasLimit (15_000_000) / BlockStorageLimit (40kb)) + const GAS_LIMIT_STORAGE_GROWTH_RATIO = 366; + beforeAll(async () => { + const { contractAddress, abi } = await deployCreateCompiledContract(context, "StorageLoop"); + storageLoopAddress = contractAddress; + storageLoopAbi = abi; + + await context.createBlock(); + }); + + for (const txnType of TransactionTypes) { + it({ + id: `T0${TransactionTypes.indexOf(txnType) + 1}`, + title: "should out of gas when gas provided is not enough to cover storage growth", + test: async function () { + // Tx is creating 5 new storage entries. So, required gas is: + // (5 * ACCOUNT_STORAGE_SIZE) * GAS_LIMIT_STORAGE_GROWTH_RATIO = 212_280 + // Execute tx with insufficient gas limit + const rawSigned = await createEthersTransaction(context, { + to: storageLoopAddress, + data: encodeFunctionData({ + abi: storageLoopAbi, + functionName: "store", + // for each transaction type, we add 5 new storage entries + args: [5 + 5 * TransactionTypes.indexOf(txnType)], + }), + gasLimit: 212_270, + }); + + const { result } = await context.createBlock(rawSigned); + // Check that the transaction failed with an out of gas error + expectEVMResult(result!.events, "Error", "OutOfGas"); + }, + }); + + it({ + id: `T0${TransactionTypes.indexOf(txnType) + 4}`, + title: "should successfully execute when updating existing storage entries (no growth)", + test: async function () { + // Update 5 existing storage entries. So, required gas should be less than 212_280 + const rawSigned = await createEthersTransaction(context, { + to: storageLoopAddress, + data: encodeFunctionData({ + abi: storageLoopAbi, + functionName: "store", + args: [5], + }), + gasLimit: 50_000, + }); + + await expectOk(context.createBlock(rawSigned)); + }, + }); + } + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts new file mode 100644 index 00000000..1f33aaa1 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts @@ -0,0 +1,43 @@ +import { describeSuite, expect } from "@moonwall/cli"; + +describeSuite({ + id: "D023501", + title: "Subscription - Logs", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should send a notification on new transaction", + test: async function () { + const logs: any[] = []; + const sub = await context.web3().eth.subscribe("logs"); + + await new Promise(async (resolve, reject) => { + sub.once("data", async (event) => { + logs.push(event); + resolve("success"); + }); + + sub.once("error", (error) => { + console.error(error); + reject(error); + }); + + await context.deployContract!("EventEmitter"); + }); + + const block = await context.viem().getBlock(); + + expect(logs[0]).to.include({ + blockHash: block.hash, + blockNumber: block.number, + data: "0x", + logIndex: 0n, + removed: false, + transactionHash: block.transactions[0], + transactionIndex: 0n, + }); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts new file mode 100644 index 00000000..2b58d33b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts @@ -0,0 +1,195 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { ALITH_CONTRACT_ADDRESSES } from "@moonwall/util"; +import type { Log } from "web3"; + +describeSuite({ + id: "D023502", + title: "Subscription - Logs", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let deployedContract: `0x${string}`; + let deployHash: `0x${string}`; + + let subSingleAddPromise: Promise; + let subMultiAddPromise: Promise; + let subTopicPromise: Promise; + let subTopicWildcardPromise: Promise; + let subTopicListPromise: Promise; + let subTopicCondPromise: Promise; + let subTopicMultiCondPromise: Promise; + let subTopicWildAndCondPromise: Promise; + + beforeAll(async () => { + const openSub = async (filter?: object) => await context.web3().eth.subscribe("logs", filter); + + const onData = (logSub: any) => { + return new Promise((resolve) => { + logSub.once("data", resolve); + }); + }; + + const [ + singleSub, + multiSub, + subTopic, + subTopicWildcard, + subTopicList, + subTopicCond, + subTopicMultiCond, + subTopicWildAndCond, + ] = await Promise.all([ + openSub({ + address: ALITH_CONTRACT_ADDRESSES[0], + }), + openSub({ + address: [ + ALITH_CONTRACT_ADDRESSES[3], + ALITH_CONTRACT_ADDRESSES[2], + ALITH_CONTRACT_ADDRESSES[1], + ALITH_CONTRACT_ADDRESSES[0], + ], + }), + openSub({ + topics: ["0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d"], + }), + openSub({ + topics: [null, "0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"], + }), + openSub({ + topics: [ + ["0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d"], + ["0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"], + ], + }), + + openSub({ + topics: [ + "0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d", + ["0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"], + ], + }), + + openSub({ + topics: [ + "0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d", + [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac", + ], + ], + }), + openSub({ + topics: [ + null, + [ + "0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ], + null, + ], + }), + ]); + + subSingleAddPromise = onData(singleSub); + subMultiAddPromise = onData(multiSub); + subTopicPromise = onData(subTopic); + subTopicWildcardPromise = onData(subTopicWildcard); + subTopicListPromise = onData(subTopicList); + subTopicCondPromise = onData(subTopicCond); + subTopicMultiCondPromise = onData(subTopicMultiCond); + subTopicWildAndCondPromise = onData(subTopicWildAndCond); + + const { contractAddress, hash } = await context.deployContract!("EventEmitter"); + deployedContract = contractAddress; + deployHash = hash; + }); + + it({ + id: "T01", + title: "should be able to filter by address", + test: async function () { + const eventLog = await subSingleAddPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T02", + title: "should be able to filter by multiple addresses", + test: async function () { + const eventLog = await subMultiAddPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T03", + title: "should be able to filter by topic", + test: async function () { + const eventLog = await subTopicPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T04", + title: "should be able to filter by topic wildcards", + test: async function () { + const eventLog = await subTopicWildcardPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T05", + title: "should be able to filter by topic list", + test: async function () { + const eventLog = await subTopicListPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T06", + title: "should be able to filter by topic conditional parameters", + test: async function () { + const eventLog = await subTopicCondPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T07", + title: "should support multiple topic conditional parameters", + test: async function () { + const eventLog = await subTopicMultiCondPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T08", + title: "should combine topic wildcards and conditional parameters", + test: async function () { + const eventLog = await subTopicWildAndCondPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts new file mode 100644 index 00000000..d053667b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts @@ -0,0 +1,30 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { BALTATHAR_ADDRESS, GLMR, createRawTransfer, sendRawTransaction } from "@moonwall/util"; +import { setTimeout } from "node:timers/promises"; + +describeSuite({ + id: "D023504", + title: "Subscription - Pending transactions", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should return a valid subscriptionId", + test: async function () { + let response: any; + const sub = await context.web3().eth.subscribe("newPendingTransactions"); + + sub.once("data", (data) => { + response = data; + }); + + const rawTx = await createRawTransfer(context, BALTATHAR_ADDRESS, GLMR); + const hash = await sendRawTransaction(context, rawTx); + await setTimeout(200); + + expect(response).not.toBeUndefined(); + expect(response).toBe(hash); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts new file mode 100644 index 00000000..ae853cfb --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts @@ -0,0 +1,61 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { ALITH_ADDRESS, BALTATHAR_ADDRESS, createRawTransfer } from "@moonwall/util"; +import { type PublicClient, createPublicClient, webSocket } from "viem"; + +describeSuite({ + id: "D023505", + title: "Subscription - Block headers", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let client: PublicClient; + + beforeAll(async () => { + const transport = webSocket(context.viem().transport.url.replace("http", "ws")); + client = createPublicClient({ + transport, + }); + }); + + it({ + id: "T01", + title: "should return a valid subscriptionId", + test: async function () { + const result = (await client.transport.request({ + method: "eth_subscribe", + params: ["newHeads"], + })) as any; + + expect(result.length).toBe(34); + }, + }); + + it({ + id: "T02", + title: "should send notification on new block", + test: async function () { + const blocks: any[] = []; + const unwatch = client.watchBlocks({ + onBlock: (block) => blocks.push(block), + }); + + await context.createBlock(createRawTransfer(context, BALTATHAR_ADDRESS, 0)); + unwatch(); + + const block = await context.viem().getBlock(); + + expect(blocks[0]).to.include({ + author: ALITH_ADDRESS.toLowerCase(), + difficulty: 0n, + extraData: "0x", + logsBloom: `0x${"0".repeat(512)}`, + miner: ALITH_ADDRESS.toLowerCase(), + sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + }); + expect(blocks[0].nonce).to.be.eq("0x0000000000000000"); + // Verify subscription roots match the block fetched via RPC + expect(blocks[0].receiptsRoot).toBe(block.receiptsRoot); + expect(blocks[0].transactionsRoot).toBe(block.transactionsRoot); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/sudo/test-sudo.ts b/test/moonwall/suites/dev/stagenet/sudo/test-sudo.ts new file mode 100644 index 00000000..b134f7cb --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/sudo/test-sudo.ts @@ -0,0 +1,123 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { + ALITH_ADDRESS, + DEFAULT_GENESIS_BALANCE, + baltathar, + generateKeyringPair, +} from "@moonwall/util"; +import { ALITH_GENESIS_TRANSFERABLE_BALANCE, verifyLatestBlockFees } from "../../../../helpers"; +import { CHARLETH_ADDRESS, ETHAN_ADDRESS } from "@moonwall/util"; + +describeSuite({ + id: "D023601", + title: "Sudo - successful forceSetBalance", + foundationMethods: "dev", + testCases: ({ context, it }) => { + it({ + id: "T01", + title: "should be able to call sudo with the right account", + test: async function () { + const { result } = await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.balances.forceSetBalance(ETHAN_ADDRESS, 0)) + ); + + const account = await context.polkadotJs().query.system.account(ETHAN_ADDRESS); + expect(account.data.free.toBigInt()).toBe(0n); + + // DataHaven has 1 more event (NewChallengeSeed) than Moonbeam, + // coming from the StorageHub ProofsDealer pallet. + expect(result!.events.length).to.eq(8); + console.log(result!.events.map((e) => e.event.toHuman())); + expect(context.polkadotJs().events.balances.BalanceSet.is(result!.events[3].event)).to.be + .true; + expect(context.polkadotJs().events.sudo.Sudid.is(result!.events[4].event)).to.be.true; + expect(context.polkadotJs().events.balances.Deposit.is(result!.events[5].event)).to.be.true; + expect(context.polkadotJs().events.system.ExtrinsicSuccess.is(result!.events[7].event)).to + .be.true; + + expect( + await context.viem().getBalance({ address: ALITH_ADDRESS }), + "diff should be null for sudo - funds are sent back" + ).to.equal(ALITH_GENESIS_TRANSFERABLE_BALANCE); + }, + }); + + it({ + id: "T02", + title: "should charge the correct amount of gas when calling sudo", + test: async function () { + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo( + context + .polkadotJs() + .tx.balances.forceSetBalance(CHARLETH_ADDRESS, DEFAULT_GENESIS_BALANCE) + ) + ); + + await verifyLatestBlockFees(context); + }, + }); + + it({ + id: "T03", + title: "should NOT be able to call sudo with another account than sudo account", + test: async function () { + const baltathar_before = await context.polkadotJs().query.system.account(CHARLETH_ADDRESS); + const { result } = await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.balances.forceSetBalance(CHARLETH_ADDRESS, 0)) + .signAsync(baltathar), + { allowFailures: true } + ); + + // Check that balance didn't change + const account = await context.polkadotJs().query.system.account(CHARLETH_ADDRESS); + expect(account.data.free.toBigInt()).toBe(DEFAULT_GENESIS_BALANCE); + + expect(result!.events.length === 8).to.be.true; + expect(context.polkadotJs().events.system.NewAccount.is(result!.events[3].event)).to.be + .true; + expect(context.polkadotJs().events.balances.Endowed.is(result!.events[4].event)).to.be.true; + expect(context.polkadotJs().events.system.ExtrinsicFailed.is(result!.events[7].event)).to.be + .true; + }, + }); + + it({ + id: "T04", + title: "should not be able to call sudo with no funds", + test: async function () { + const newSigner = generateKeyringPair(); + + await context.createBlock(context.polkadotJs().tx.sudo.setKey(newSigner.address), { + allowFailures: false, + }); + + expect((await context.polkadotJs().query.sudo.key()).unwrap().toString()).toBe( + newSigner.address + ); + + await expect( + async () => + await context.createBlock( + context + .polkadotJs() + .tx.sudo.sudo(context.polkadotJs().tx.balances.forceSetBalance(CHARLETH_ADDRESS, 0)) + .signAsync(newSigner) + ) + ).rejects.toThrowError( + "1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low" + ); + + expect(await context.viem().getBalance({ address: CHARLETH_ADDRESS })).to.equal( + DEFAULT_GENESIS_BALANCE + ); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/txpool/test-txpool-future.ts b/test/moonwall/suites/dev/stagenet/txpool/test-txpool-future.ts new file mode 100644 index 00000000..6f6ced8f --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/txpool/test-txpool-future.ts @@ -0,0 +1,69 @@ +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { alith, createEthersTransaction, sendRawTransaction } from "@moonwall/util"; +import { encodeDeployData, toHex } from "viem"; + +describeSuite({ + id: "D023802", + title: "TxPool - Future Ethereum transaction", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let txHash: string; + let deployData: string; + + beforeAll(async () => { + const { abi, bytecode } = fetchCompiledContract("MultiplyBy7"); + deployData = encodeDeployData({ + abi, + bytecode, + }); + + const rawTxn = await createEthersTransaction(context, { + data: deployData, + gasLimit: 1048576, + nonce: 1, // future nonce + }); + txHash = await sendRawTransaction(context, rawTxn); + }); + + it({ + id: "T01", + title: "should appear in the txpool inspection", + test: async function () { + const inspect = (await context + .viem() + .transport.request({ method: "txpool_inspect" })) as any; + // web3 rpc returns lowercase + const data = inspect.queued[alith.address.toLowerCase()][toHex(1)]; + expect(data).to.not.be.undefined; + expect(data).to.be.equal( + "0x0000000000000000000000000000000000000000: 0 wei + 1048576 gas x 10000000000 wei" + ); + }, + }); + + it({ + id: "T02", + title: "should appear in the txpool content", + test: async function () { + const content = (await context + .viem() + .transport.request({ method: "txpool_content" })) as any; + // web3 rpc returns lowercase + const data = content.queued[alith.address.toLowerCase()][toHex(1)]; + expect(data).toMatchObject({ + blockHash: null, + blockNumber: null, + from: alith.address.toLowerCase(), + gas: "0x100000", + gasPrice: "0x2540be400", + hash: txHash, + input: deployData, + nonce: toHex(1), + to: null, + transactionIndex: null, + value: "0x0", + }); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/txpool/test-txpool-pending.ts b/test/moonwall/suites/dev/stagenet/txpool/test-txpool-pending.ts new file mode 100644 index 00000000..c2f86188 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/txpool/test-txpool-pending.ts @@ -0,0 +1,84 @@ +import { beforeAll, describeSuite, expect, fetchCompiledContract } from "@moonwall/cli"; +import { ALITH_ADDRESS, createEthersTransaction, sendRawTransaction } from "@moonwall/util"; +import { encodeDeployData, toHex } from "viem"; + +describeSuite({ + id: "D023807", + title: "TxPool - Pending Ethereum transaction", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let txHash: string; + + beforeAll(async () => { + const { abi, bytecode } = fetchCompiledContract("MultiplyBy7"); + const deployData = encodeDeployData({ + abi, + bytecode, + }); + + const rawTxn = await createEthersTransaction(context, { + data: deployData, + gasLimit: 1048576, + nonce: 0, + }); + txHash = await sendRawTransaction(context, rawTxn); + }); + + it({ + id: "T01", + title: "should appear in the txpool inspection", + test: async function () { + const inspect = (await context + .viem() + .transport.request({ method: "txpool_inspect" })) as any; + + // web3 rpc returns lowercase + const data = inspect.pending[ALITH_ADDRESS.toLowerCase()][toHex(0)]; + expect(data).to.not.be.undefined; + expect(data).to.be.equal( + "0x0000000000000000000000000000000000000000: 0 wei + 1048576 gas x 10000000000 wei" + ); + }, + }); + + it({ + id: "T02", + title: "should be marked as pending", + test: async function () { + const pendingTransaction = await context + .viem() + .getTransaction({ hash: txHash as `0x${string}` }); + + // pending transactions do not know yet to which block they belong to + expect(pendingTransaction).to.include({ + blockNumber: null, + hash: txHash, + }); + }, + }); + + it({ + id: "T03", + title: "should appear in the txpool content", + test: async function () { + const content = (await context + .viem() + .transport.request({ method: "txpool_content" })) as any; + + // web3 rpc returns lowercase + const data = content.pending[ALITH_ADDRESS.toLowerCase()][toHex(0)]; + expect(data).to.include({ + blockHash: null, + blockNumber: null, + from: ALITH_ADDRESS.toLowerCase(), + gas: "0x100000", + gasPrice: "0x2540be400", + hash: txHash, + nonce: toHex(0), + to: null, + value: "0x0", + }); + }, + }); + }, +}); diff --git a/test/package.json b/test/package.json index c18048eb..dc2da493 100644 --- a/test/package.json +++ b/test/package.json @@ -30,6 +30,8 @@ "test:e2e:parallel": "bun scripts/test-parallel.ts", "moonwall:test": "moonwall test dev_datahaven", "moonwall:run": "moonwall run dev_datahaven", + "submitter": "bun run tools/validator-set-submitter/main.ts run", + "submitter:dry-run": "bun run tools/validator-set-submitter/main.ts run --dry-run", "typecheck": "tsc --noEmit", "tsgo": "tsgo tsc --noEmit --pretty --skipLibCheck", "postinstall": "papi" diff --git a/test/resources/datahaven-integration-test-flow.md b/test/resources/datahaven-integration-test-flow.md index 82b2a7f6..4dcc14ce 100644 --- a/test/resources/datahaven-integration-test-flow.md +++ b/test/resources/datahaven-integration-test-flow.md @@ -207,7 +207,6 @@ Another testing scenario is testing the operational aspects of the validator set 3. **Slashing Mechanisms** - Test slashing for various offenses - - Test veto committee mechanisms 4. **Operator Set Modifications** - Modify operator sets from Ethereum diff --git a/test/scripts/deploy-contracts.ts b/test/scripts/deploy-contracts.ts index 934426ef..7ef7488d 100644 --- a/test/scripts/deploy-contracts.ts +++ b/test/scripts/deploy-contracts.ts @@ -9,6 +9,7 @@ import { dataHavenServiceManagerAbi } from "../contract-bindings/generated"; interface ContractDeploymentOptions { chain?: string; + environment?: string; rpcUrl?: string; privateKey?: string | undefined; verified?: boolean; @@ -18,6 +19,15 @@ interface ContractDeploymentOptions { txExecution?: boolean; } +/** + * Builds the network identifier from chain and optional environment + * When environment is specified: {environment}-{chain} (e.g., "stagenet-hoodi") + * When environment is not specified: {chain} (e.g., "hoodi") + */ +export const buildNetworkId = (chain: string, environment?: string): string => { + return environment ? `${environment}-${chain}` : chain; +}; + /** * Validates deployment parameters */ @@ -52,20 +62,23 @@ export const buildContracts = async () => { * Constructs the deployment command */ export const constructDeployCommand = (options: ContractDeploymentOptions): string => { - const { chain, rpcUrl, verified, blockscoutBackendUrl } = options; + const { chain, environment, rpcUrl, verified, blockscoutBackendUrl } = options; const deploymentScript = !chain || chain === "anvil" ? "script/deploy/DeployLocal.s.sol" - : "script/deploy/DeployTestnet.s.sol"; + : "script/deploy/DeployLive.s.sol"; - logger.info(`🚀 Deploying contracts to ${chain} using ${deploymentScript}`); + // Build the network identifier for display and environment variable + const networkId = buildNetworkId(chain || "anvil", environment); + + logger.info(`🚀 Deploying contracts to ${networkId} using ${deploymentScript}`); let deployCommand = `forge script ${deploymentScript} --rpc-url ${rpcUrl} --color never -vv --no-rpc-rate-limit --non-interactive --broadcast`; - // Add environment variable for chain if specified + // Add environment variables for network (used by Solidity scripts for config/output file naming) if (chain) { - deployCommand = `NETWORK=${chain} ${deployCommand}`; + deployCommand = `NETWORK=${networkId} ${deployCommand}`; } if (verified && blockscoutBackendUrl) { @@ -110,33 +123,29 @@ export const updateParameters = async ( parameterCollection: ParameterCollection, chain?: string ) => { - try { - const deployments = await parseDeploymentsFile(chain); - const gatewayAddress = deployments.Gateway; - const serviceManagerAddress = deployments.ServiceManager; + const deployments = await parseDeploymentsFile(chain); + const gatewayAddress = deployments.Gateway; + const serviceManagerAddress = deployments.ServiceManager; - if (gatewayAddress) { - logger.debug(`📝 Adding EthereumGatewayAddress parameter: ${gatewayAddress}`); + if (gatewayAddress) { + logger.debug(`📝 Adding EthereumGatewayAddress parameter: ${gatewayAddress}`); - parameterCollection.addParameter({ - name: "EthereumGatewayAddress", - value: gatewayAddress - }); - } else { - logger.warn("⚠️ Gateway address not found in deployments file"); - } + parameterCollection.addParameter({ + name: "EthereumGatewayAddress", + value: gatewayAddress + }); + } else { + logger.warn("⚠️ Gateway address not found in deployments file"); + } - if (serviceManagerAddress) { - logger.debug(`📝 Adding DatahavenServiceManagerAddress parameter: ${serviceManagerAddress}`); - parameterCollection.addParameter({ - name: "DatahavenServiceManagerAddress", - value: serviceManagerAddress - }); - } else { - logger.warn("⚠️ ServiceManager address not found in deployments file"); - } - } catch (error) { - logger.error(`Failed to read parameters from deployment: ${error}`); + if (serviceManagerAddress) { + logger.debug(`📝 Adding DatahavenServiceManagerAddress parameter: ${serviceManagerAddress}`); + parameterCollection.addParameter({ + name: "DatahavenServiceManagerAddress", + value: serviceManagerAddress + }); + } else { + logger.warn("⚠️ ServiceManager address not found in deployments file"); } }; @@ -146,6 +155,7 @@ export const updateParameters = async ( */ export const deployContracts = async (options: { chain: string; + environment?: string; rpcUrl?: string; privateKey?: string | undefined; verified?: boolean; @@ -160,6 +170,9 @@ export const deployContracts = async (options: { throw new Error(`Unsupported chain: ${options.chain}`); } + // Build network identifier for config/deployment file naming + const networkId = buildNetworkId(options.chain, options.environment); + const finalRpcUrl = options.rpcUrl || chainConfig.RPC_URL; const isLocalChain = options.chain === "anvil"; const txExecutionEnabled = options.txExecution ?? isLocalChain; @@ -173,7 +186,7 @@ export const deployContracts = async (options: { } if (!resolvedAvsOwnerAddress && isLocalChain) { - const config = await loadChainConfig(options.chain); + const config = await loadChainConfig(options.chain, options.environment); resolvedAvsOwnerAddress = config?.avs?.avsOwner; } @@ -191,6 +204,7 @@ export const deployContracts = async (options: { const deploymentOptions: ContractDeploymentOptions = { chain: options.chain, + environment: options.environment, rpcUrl: finalRpcUrl, privateKey: options.privateKey, verified: options.verified, @@ -209,13 +223,13 @@ export const deployContracts = async (options: { // Construct and execute deployment const deployCommand = constructDeployCommand(deploymentOptions); const env = buildDeploymentEnv(deploymentOptions); - await executeDeployment(deployCommand, undefined, options.chain, env); + await executeDeployment(deployCommand, undefined, networkId, env); if (!txExecutionEnabled) { - await emitOwnerTransactionCalldata(options.chain); + await emitOwnerTransactionCalldata(networkId); } - logger.success(`DataHaven contracts deployed successfully to ${options.chain}`); + logger.success(`DataHaven contracts deployed successfully to ${networkId}`); }; const normalizePrivateKey = (key?: string): `0x${string}` | undefined => { diff --git a/test/scripts/fund-providers.ts b/test/scripts/fund-providers.ts index 1487fd2e..098226ea 100644 --- a/test/scripts/fund-providers.ts +++ b/test/scripts/fund-providers.ts @@ -7,32 +7,6 @@ export interface FundProvidersOptions { launchedNetwork: LaunchedNetwork; } -/** - * Provider account information for MSP and BSP nodes. - * - * DataHaven uses AccountId20 (Ethereum-style 20-byte addresses). - * In dev chains, CHARLETH and DOROTHY are pre-funded development accounts - * that correspond to //Charlie and //Dave derivations. - * - * For StorageHub providers, we use: - * - CHARLETH (//Charlie equivalent) for MSP - * - DOROTHY (//Dave equivalent) for BSP (as //Eve might not have pre-funded AccountId20) - */ -const PROVIDER_ACCOUNTS = { - // MSP account (Charleth = Charlie in AccountId20 format) - msp: { - name: "Charleth", - address: SUBSTRATE_FUNDED_ACCOUNTS.CHARLETH.publicKey, // 20-byte address - derivation: "//Charlie" - }, - // BSP account (Dorothy = Dave in AccountId20 format, using instead of Eve) - bsp: { - name: "Dorothy", - address: SUBSTRATE_FUNDED_ACCOUNTS.DOROTHY.publicKey, // 20-byte address - derivation: "//Dave" // Using Dave instead of Eve for BSP - } -} as const; - /** * Minimum balance required for provider operations. * This includes: @@ -61,30 +35,34 @@ export async function fundProviders(options: FundProvidersOptions): Promise { // Use a higher max size (3MB) to handle the large state-diff.json file const result = - await $`bun run biome format --files-max-size=3000000 --write ${STATE_DIFF_PATH}`.quiet(); + await $`bun run biome format --files-max-size=4000000 --write ${STATE_DIFF_PATH}`.quiet(); if (result.exitCode !== 0) { logger.warn("⚠️ Biome formatting had issues, but continuing..."); diff --git a/test/scripts/set-datahaven-parameters.ts b/test/scripts/set-datahaven-parameters.ts index 13b127d5..f015f6ee 100644 --- a/test/scripts/set-datahaven-parameters.ts +++ b/test/scripts/set-datahaven-parameters.ts @@ -50,8 +50,20 @@ export const setDataHavenParameters = async ( const result = await tx.signAndSubmit(signer); - if (!result.ok) { - logger.error(`❌ Transaction failed: ${result.block.hash}`); + // sudo always returns Ok at the extrinsic level — check the Sudid event + // for the inner call result + const sudidEvent = result.events.find( + (e: any) => e.type === "Sudo" && e.value?.type === "Sudid" + ); + + if (!sudidEvent) { + logger.error("❌ Sudo.Sudid event not found in transaction events"); + return false; + } + + const sudoResult = (sudidEvent.value as any).value.sudo_result; + if (sudoResult.type === "Err") { + logger.error(`❌ Sudo inner call failed: ${JSON.stringify(sudoResult)}`); return false; } diff --git a/test/scripts/setup-validators.ts b/test/scripts/setup-validators.ts index 4edbbb93..8adce8f5 100644 --- a/test/scripts/setup-validators.ts +++ b/test/scripts/setup-validators.ts @@ -124,6 +124,29 @@ export const setupValidators = async (options: SetupValidatorsOptions): Promise< logger.success(`Successfully registered validator ${validator.publicKey}`); } + // Allocate stake for each validator (must run in a separate script because + // the allocation delay needs at least 1 block after registerAsOperator) + logger.info("📊 Allocating operator stake..."); + for (const [i, validator] of validatorsToRegister.entries()) { + logger.info(`📊 Allocating stake for validator ${i} (${validator.publicKey})`); + + const env = { + ...process.env, + NETWORK: networkName, + OPERATOR_PRIVATE_KEY: validator.privateKey, + OPERATOR_SOLOCHAIN_ADDRESS: validator.solochainAddress || "" + }; + + const allocateCommand = `forge script script/transact/AllocateOperatorStake.s.sol --rpc-url ${rpcUrl} --broadcast --no-rpc-rate-limit --non-interactive`; + await runShellCommandWithLogger(allocateCommand, { + env, + cwd: "../contracts", + logLevel: "debug" + }); + + logger.success(`Successfully allocated stake for validator ${validator.publicKey}`); + } + return true; }; diff --git a/test/scripts/update-validator-set.ts b/test/scripts/update-validator-set.ts index 26b9064f..bc95ab1d 100644 --- a/test/scripts/update-validator-set.ts +++ b/test/scripts/update-validator-set.ts @@ -7,6 +7,7 @@ import { logger } from "../utils/index"; interface UpdateValidatorSetOptions { rpcUrl: string; + targetEra?: bigint; } /** @@ -49,8 +50,15 @@ export const updateValidatorSet = async (options: UpdateValidatorSetOptions): Pr const executionFee = "100000000000000000"; // 0.1 ETH const relayerFee = "200000000000000000"; // 0.2 ETH const value = "300000000000000000"; // 0.3 ETH (sum of fees) + const targetEra = options.targetEra ?? 1n; - const sendCommand = `${castExecutable} send --private-key ${ownerPrivateKey} --value ${value} ${serviceManagerAddress} "sendNewValidatorSet(uint128,uint128)" ${executionFee} ${relayerFee} --rpc-url ${rpcUrl}`; + if (options.targetEra === undefined) { + logger.warn( + "No target era specified; defaulting to era 1. Use --target-era for already-running networks." + ); + } + + const sendCommand = `${castExecutable} send --private-key ${ownerPrivateKey} --value ${value} ${serviceManagerAddress} "sendNewValidatorSetForEra(uint64,uint128,uint128)" ${targetEra} ${executionFee} ${relayerFee} --rpc-url ${rpcUrl}`; logger.debug(`Running command: ${sendCommand}`); @@ -89,6 +97,7 @@ if (import.meta.main) { const args = process.argv.slice(2); const options: { rpcUrl?: string; + targetEra?: bigint; } = {}; // Extract RPC URL @@ -97,6 +106,12 @@ if (import.meta.main) { options.rpcUrl = args[rpcUrlIndex + 1]; } + // Extract target era + const targetEraIndex = args.indexOf("--target-era"); + if (targetEraIndex !== -1 && targetEraIndex + 1 < args.length) { + options.targetEra = BigInt(args[targetEraIndex + 1]); + } + // Check required parameters if (!options.rpcUrl) { console.error("Error: --rpc-url parameter is required"); @@ -105,7 +120,8 @@ if (import.meta.main) { // Run update updateValidatorSet({ - rpcUrl: options.rpcUrl + rpcUrl: options.rpcUrl, + targetEra: options.targetEra }).catch((error) => { console.error("Validator set update failed:", error); process.exit(1); diff --git a/test/tools/validator-set-submitter/Dockerfile b/test/tools/validator-set-submitter/Dockerfile new file mode 100644 index 00000000..5e7d9b44 --- /dev/null +++ b/test/tools/validator-set-submitter/Dockerfile @@ -0,0 +1,37 @@ +# Validator Set Submitter image +# +# Build from the repository root: +# docker build -f test/tools/validator-set-submitter/Dockerfile \ +# -t datahavenxyz/validator-set-submitter:local . +# +# Runtime expectations: +# - Mount a config file at /config/config.yml +# - Provide SUBMITTER_PRIVATE_KEY (or pass --submitter-private-key) +# - Set service_manager_address in config.yml (contracts/deployments is not in the image) + +FROM oven/bun:1.3.3-slim AS deps + +WORKDIR /app + +COPY test/package.json test/bun.lock test/tsconfig.json ./ +COPY test/.papi ./.papi +RUN bun install --frozen-lockfile --production + +FROM oven/bun:1.3.3-slim + +WORKDIR /app + +RUN useradd -m -u 1001 -U -s /bin/sh -d /submitter submitter + +COPY --from=deps /app/node_modules ./node_modules +COPY test/tsconfig.json test/bunfig.toml ./ +COPY test/tools/validator-set-submitter/ ./tools/validator-set-submitter/ +COPY test/contract-bindings/ ./contract-bindings/ +COPY test/utils/ ./utils/ + +ENV NODE_ENV=production + +USER submitter + +ENTRYPOINT ["bun", "run", "tools/validator-set-submitter/main.ts", "run"] +CMD ["--config", "/config/config.yml"] diff --git a/test/tools/validator-set-submitter/README.md b/test/tools/validator-set-submitter/README.md new file mode 100644 index 00000000..62a2f9f9 --- /dev/null +++ b/test/tools/validator-set-submitter/README.md @@ -0,0 +1,108 @@ +# Validator Set Submitter + +Long-running daemon that automatically submits validator-set updates from Ethereum to DataHaven each era via Snowbridge. + +## How it works + +The submitter subscribes to finalized `Session.CurrentIndex` changes on DataHaven. On each session change it evaluates: + +1. Is `ActiveEra` set? +2. Has `targetEra` (`ActiveEra + 1`) already been processed? +3. Is `ExternalIndex` already at or past `targetEra`? +4. Is the current session the last session of the era? + +If all preconditions are met, it calls `sendNewValidatorSetForEra` on the ServiceManager contract. Each era gets a single submission attempt — if it fails, the era is missed and the submitter moves on to the next. + +## Prerequisites + +- The submitter account must be registered on-chain via `setValidatorSetSubmitter` on the ServiceManager. +- An Ethereum RPC endpoint and a DataHaven WebSocket endpoint must be reachable. +- Dependencies installed: `bun i` from the `test/` directory. + +## Configuration + +Copy `config.yml` and fill in your values: + +```yaml +# Connections +ethereum_rpc_url: "http://127.0.0.1:8545" +datahaven_ws_url: "ws://127.0.0.1:9944" + +# Optional if provided via --submitter-private-key or SUBMITTER_PRIVATE_KEY env var +# The private key of the account authorized as validatorSetSubmitter +submitter_private_key: "0x..." + +# Optional — falls back to contracts/deployments/{network_id}.json +# service_manager_address: "0x..." +network_id: "anvil" + +# Fees (in ETH, sent as msg.value to cover Snowbridge relay costs) +execution_fee: "0.1" +relayer_fee: "0.2" +``` + +## Usage + +From the `test/` directory: + +```bash +# Start the submitter +bun tools/validator-set-submitter/main.ts run + +# With a custom config path +bun tools/validator-set-submitter/main.ts run --config ./path/to/config.yml + +# Provide private key via environment variable +SUBMITTER_PRIVATE_KEY=0x... bun tools/validator-set-submitter/main.ts run + +# Provide private key via CLI argument +bun tools/validator-set-submitter/main.ts run --submitter-private-key 0x... + +# Dry run — logs what would be submitted without sending transactions +bun tools/validator-set-submitter/main.ts run --dry-run +``` + +Private key precedence is: `--submitter-private-key` > `SUBMITTER_PRIVATE_KEY` > `submitter_private_key` in config file. + +## Docker + +Build the image from the repository root: + +```bash +docker build -f test/tools/validator-set-submitter/Dockerfile \ + -t datahavenxyz/validator-set-submitter:local . +``` + +Run the submitter with mounted config and env private key: + +```bash +docker run --rm \ + -v "$(pwd)/test/tools/validator-set-submitter/config.yml:/config/config.yml:ro" \ + -e SUBMITTER_PRIVATE_KEY=0x... \ + datahavenxyz/validator-set-submitter:local +``` + +Dry run: + +```bash +docker run --rm \ + -v "$(pwd)/test/tools/validator-set-submitter/config.yml:/config/config.yml:ro" \ + -e SUBMITTER_PRIVATE_KEY=0x... \ + datahavenxyz/validator-set-submitter:local --dry-run +``` + +The Docker image does not include `contracts/deployments/*.json`. In containerized runs, set `service_manager_address` in your config. + +## Startup checks + +On launch the submitter verifies: + +- Ethereum RPC is reachable (fetches current block number). +- DataHaven WebSocket is reachable (fetches current block header). +- The configured private key matches the on-chain `validatorSetSubmitter` address. + +If any check fails, the process exits immediately. + +## Shutdown + +Send `SIGINT` (Ctrl+C) or `SIGTERM`. The submitter unsubscribes from session changes and tears down connections cleanly. diff --git a/test/tools/validator-set-submitter/chain.ts b/test/tools/validator-set-submitter/chain.ts new file mode 100644 index 00000000..8899b33c --- /dev/null +++ b/test/tools/validator-set-submitter/chain.ts @@ -0,0 +1,61 @@ +import type { DataHavenApi } from "utils/papi"; +import type { PublicClient } from "viem"; +import { dataHavenServiceManagerAbi } from "../../contract-bindings"; + +/** + * Reads the current ActiveEra from the ExternalValidators pallet. + * Returns `{ index, start }` where `index` is the era number. + */ +export async function getActiveEra(dhApi: DataHavenApi) { + const era = await dhApi.query.ExternalValidators.ActiveEra.getValue(); + return era; +} + +/** + * Reads the ExternalIndex — the latest era that has been confirmed on-chain + * via an inbound Snowbridge message. + */ +export async function getExternalIndex(dhApi: DataHavenApi): Promise { + const index = await dhApi.query.ExternalValidators.ExternalIndex.getValue(); + return BigInt(index); +} + +/** + * The target era for the next submission is always ActiveEra + 1. + */ +export function computeTargetEra(activeEraIndex: number): bigint { + return BigInt(activeEraIndex + 1); +} + +/** + * Reads the on-chain `validatorSetSubmitter` address from the ServiceManager contract. + */ +export async function getOnChainSubmitter( + publicClient: PublicClient, + serviceManagerAddress: `0x${string}` +): Promise<`0x${string}`> { + const submitter = await publicClient.readContract({ + address: serviceManagerAddress, + abi: dataHavenServiceManagerAbi, + functionName: "validatorSetSubmitter" + }); + return submitter as `0x${string}`; +} + +/** + * Returns true if the current session is the last session of the active era. + * Uses the on-chain SessionsPerEra constant and ErasStartSessionIndex storage. + */ +export async function isLastSessionOfEra(dhApi: DataHavenApi): Promise { + const activeEra = await dhApi.query.ExternalValidators.ActiveEra.getValue(); + if (!activeEra) return false; + + const sessionsPerEra = await dhApi.constants.ExternalValidators.SessionsPerEra(); + const eraStartSession = await dhApi.query.ExternalValidators.ErasStartSessionIndex.getValue( + activeEra.index + ); + if (eraStartSession === undefined) return false; + + const currentSession = await dhApi.query.Session.CurrentIndex.getValue(); + return currentSession >= eraStartSession + sessionsPerEra - 1; +} diff --git a/test/tools/validator-set-submitter/config.ts b/test/tools/validator-set-submitter/config.ts new file mode 100644 index 00000000..419ea8d4 --- /dev/null +++ b/test/tools/validator-set-submitter/config.ts @@ -0,0 +1,101 @@ +import { parseDeploymentsFile } from "utils"; +import { parseEther } from "viem"; +import { parse as parseYaml } from "yaml"; + +export interface SubmitterConfig { + ethereumRpcUrl: string; + datahavenWsUrl: string; + submitterPrivateKey: `0x${string}`; + serviceManagerAddress: `0x${string}`; + networkId: string; + executionFee: bigint; + relayerFee: bigint; + dryRun: boolean; +} + +interface CliOverrides { + dryRun?: boolean; + submitterPrivateKey?: string; +} + +export async function loadConfig( + configPath: string, + cli: CliOverrides = {} +): Promise { + const file = Bun.file(configPath); + if (!(await file.exists())) { + throw new Error(`Config file not found: ${configPath}`); + } + const raw = parseYaml(await file.text()) as Record; + + const ethereumRpcUrl = requireString(raw, "ethereum_rpc_url"); + const datahavenWsUrl = requireString(raw, "datahaven_ws_url"); + const submitterPrivateKey = resolveSubmitterPrivateKey(raw, cli.submitterPrivateKey); + const networkId = optionalString(raw, "network_id") ?? "anvil"; + + let serviceManagerAddress = optionalHexString(raw, "service_manager_address"); + if (!serviceManagerAddress) { + const deployments = await parseDeploymentsFile(networkId); + serviceManagerAddress = deployments.ServiceManager; + } + + const executionFee = parseEther(optionalString(raw, "execution_fee") ?? "0.1"); + const relayerFee = parseEther(optionalString(raw, "relayer_fee") ?? "0.2"); + + return { + ethereumRpcUrl, + datahavenWsUrl, + submitterPrivateKey, + serviceManagerAddress, + networkId, + executionFee, + relayerFee, + dryRun: cli.dryRun ?? false + }; +} + +function resolveSubmitterPrivateKey( + raw: Record, + cliPrivateKey?: string +): `0x${string}` { + const submitterPrivateKey = + cliPrivateKey ?? + process.env.SUBMITTER_PRIVATE_KEY ?? + optionalString(raw, "submitter_private_key"); + + if (!submitterPrivateKey || submitterPrivateKey.length === 0) { + throw new Error( + "Missing submitter private key. Provide --submitter-private-key, SUBMITTER_PRIVATE_KEY, or submitter_private_key in config." + ); + } + + if (!/^0x[0-9a-fA-F]{64}$/.test(submitterPrivateKey)) { + throw new Error("Submitter private key must be a 66-character hex string (0x + 64 hex chars)"); + } + + return submitterPrivateKey as `0x${string}`; +} + +function requireString(raw: Record, key: string): string { + const val = raw[key]; + if (typeof val !== "string" || val.length === 0) { + throw new Error(`Missing required config field: ${key}`); + } + return val; +} + +function optionalString(raw: Record, key: string): string | undefined { + const val = raw[key]; + if (val === undefined || val === null) return undefined; + if (typeof val !== "string") return String(val); + return val; +} + +function optionalHexString(raw: Record, key: string): `0x${string}` | undefined { + const val = optionalString(raw, key); + if (!val) return undefined; + if (!val.startsWith("0x")) { + throw new Error(`Config field ${key} must start with 0x`); + } + return val as `0x${string}`; +} diff --git a/test/tools/validator-set-submitter/config.yml b/test/tools/validator-set-submitter/config.yml new file mode 100644 index 00000000..4c883359 --- /dev/null +++ b/test/tools/validator-set-submitter/config.yml @@ -0,0 +1,21 @@ +# Validator Set Submitter Configuration +# Copy this file and update values for your environment. + +# Connections +ethereum_rpc_url: "http://127.0.0.1:8545" +datahaven_ws_url: "ws://127.0.0.1:9944" + +# Credentials +# Optional if provided via --submitter-private-key or SUBMITTER_PRIVATE_KEY env var +# The private key of the account authorized as validatorSetSubmitter on the ServiceManager +submitter_private_key: "0x..." + +# Contract +# Optional — if omitted, falls back to contracts/deployments/{network_id}.json +# Note: Docker image does not include contracts/deployments; set this explicitly when running in Docker. +# service_manager_address: "0x..." +network_id: "anvil" + +# Fees (in ETH, sent as msg.value to cover Snowbridge relay costs) +execution_fee: "0.1" +relayer_fee: "0.2" diff --git a/test/tools/validator-set-submitter/main.ts b/test/tools/validator-set-submitter/main.ts new file mode 100644 index 00000000..3f0052ab --- /dev/null +++ b/test/tools/validator-set-submitter/main.ts @@ -0,0 +1,92 @@ +import { Command } from "@commander-js/extra-typings"; +import { logger } from "utils/logger"; +import { privateKeyToAccount } from "viem/accounts"; +import { getOnChainSubmitter } from "./chain"; +import { loadConfig } from "./config"; +import { createClients, startSubmitter } from "./submitter"; + +const program = new Command() + .name("validator-set-submitter") + .description("Automatically submits validator-set updates from Ethereum to DataHaven each era"); + +program + .command("run") + .description("Start the submitter daemon") + .option( + "--config ", + "Path to YAML config file", + "./tools/validator-set-submitter/config.yml" + ) + .option( + "--submitter-private-key ", + "Override submitter private key (or use SUBMITTER_PRIVATE_KEY env var)" + ) + .option("--dry-run", "Log what would be submitted without sending transactions", false) + .action(async (opts) => { + const config = await loadConfig(opts.config, { + dryRun: opts.dryRun, + submitterPrivateKey: opts.submitterPrivateKey + }); + + logger.info("Validator Set Submitter starting..."); + logger.info(`Ethereum RPC: ${config.ethereumRpcUrl}`); + logger.info(`DataHaven WS: ${config.datahavenWsUrl}`); + logger.info(`ServiceManager: ${config.serviceManagerAddress}`); + logger.info(`Dry run: ${config.dryRun}`); + + const clients = createClients(config); + + // Startup self-checks + try { + const blockNumber = await clients.publicClient.getBlockNumber(); + logger.info(`Ethereum connected — block #${blockNumber}`); + } catch (err) { + logger.error(`Cannot connect to Ethereum RPC: ${err}`); + process.exit(1); + } + + try { + const header = await clients.papiClient.getBlockHeader(); + logger.info(`DataHaven connected — block #${header.number}`); + } catch (err) { + logger.error(`Cannot connect to DataHaven WS: ${err}`); + process.exit(1); + } + + // Verify our account is authorized on-chain + try { + const account = privateKeyToAccount(config.submitterPrivateKey); + const onChainSubmitter = await getOnChainSubmitter( + clients.publicClient, + config.serviceManagerAddress + ); + if (onChainSubmitter.toLowerCase() !== account.address.toLowerCase()) { + logger.error( + `Account ${account.address} is not the authorized submitter (on-chain: ${onChainSubmitter})` + ); + process.exit(1); + } + logger.info(`Authorized submitter verified: ${account.address}`); + } catch (err) { + logger.error(`Failed to verify submitter authorization: ${err}`); + process.exit(1); + } + + // Graceful shutdown + const ac = new AbortController(); + const shutdown = () => { + logger.info("Shutdown signal received, stopping..."); + ac.abort(); + }; + process.on("SIGINT", shutdown); + process.on("SIGTERM", shutdown); + + try { + await startSubmitter(clients, config, ac.signal); + } finally { + clients.papiClient.destroy(); + logger.info("Submitter stopped, PAPI client destroyed"); + } + }); + +program.parse(); diff --git a/test/tools/validator-set-submitter/submitter.ts b/test/tools/validator-set-submitter/submitter.ts new file mode 100644 index 00000000..ad6d4593 --- /dev/null +++ b/test/tools/validator-set-submitter/submitter.ts @@ -0,0 +1,209 @@ +import { EMPTY, exhaustMap } from "rxjs"; +import { logger } from "utils/logger"; +import { createPapiConnectors, type DataHavenApi } from "utils/papi"; +import { + type Account, + createPublicClient, + createWalletClient, + decodeEventLog, + http, + type PublicClient, + type WalletClient +} from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { dataHavenServiceManagerAbi, gatewayAbi } from "../../contract-bindings"; +import { computeTargetEra, getActiveEra, getExternalIndex, isLastSessionOfEra } from "./chain"; +import type { SubmitterConfig } from "./config"; + +interface SubmitterClients { + publicClient: PublicClient; + walletClient: WalletClient, undefined, Account>; + dhApi: DataHavenApi; + papiClient: ReturnType["client"]; +} + +const RECEIPT_TIMEOUT_MS = 120_000; + +export function createClients(config: SubmitterConfig): SubmitterClients { + const account = privateKeyToAccount(config.submitterPrivateKey); + const transport = http(config.ethereumRpcUrl); + + const publicClient = createPublicClient({ transport }); + const walletClient = createWalletClient({ account, transport }); + const { client: papiClient, typedApi: dhApi } = createPapiConnectors(config.datahavenWsUrl); + + return { publicClient, walletClient, dhApi, papiClient }; +} + +/** + * Returns a promise that resolves when the signal is aborted. + */ +function onAbort(signal: AbortSignal): Promise { + if (signal.aborted) return Promise.resolve(); + return new Promise((resolve) => + signal.addEventListener("abort", () => resolve(), { once: true }) + ); +} + +/** + * Waits for a transaction receipt with a hard timeout, and exits early on abort. + */ +async function waitForReceiptWithAbort( + publicClient: PublicClient, + hash: `0x${string}`, + signal: AbortSignal +) { + return Promise.race([ + publicClient.waitForTransactionReceipt({ + hash, + timeout: RECEIPT_TIMEOUT_MS + }), + onAbort(signal).then(() => { + throw signal.reason ?? new Error("Aborted while waiting for transaction receipt"); + }) + ]); +} + +/** + * Creates a tick handler that closes over submission state. + * Each call evaluates a session change and submits if eligible. + */ +function createTicker(clients: SubmitterClients, config: SubmitterConfig, signal: AbortSignal) { + let submittedEra: bigint | undefined; + + return async (currentSession: number): Promise => { + const { dhApi } = clients; + + const activeEra = await getActiveEra(dhApi); + if (!activeEra) { + logger.warn("ActiveEra not set yet"); + return; + } + + const targetEra = computeTargetEra(activeEra.index); + if (submittedEra === targetEra) return; + + const externalIndex = await getExternalIndex(dhApi); + if (externalIndex >= targetEra) { + submittedEra = targetEra; + return; + } + + if (!(await isLastSessionOfEra(dhApi))) return; + + logger.info( + `Session=${currentSession} ActiveEra=${activeEra.index} TargetEra=${targetEra} ExternalIndex=${externalIndex}` + ); + + const succeeded = await submitForEra(clients, config, targetEra, signal); + if (succeeded) submittedEra = targetEra; + }; +} + +/** + * Watches finalized session changes and submits validator sets when eligible. + * Runs until the signal is aborted. + */ +export async function startSubmitter( + clients: SubmitterClients, + config: SubmitterConfig, + signal: AbortSignal +): Promise { + const { dhApi } = clients; + const tick = createTicker(clients, config, signal); + + logger.info("Submitter started — watching session changes"); + + const sub = dhApi.query.Session.CurrentIndex.watchValue("finalized") + .pipe( + exhaustMap((currentSession) => { + if (signal.aborted) return EMPTY; + return tick(currentSession).catch((err) => { + if (!signal.aborted) logger.error(`Tick error: ${err}`); + }); + }) + ) + .subscribe({ + error: (err) => { + if (!signal.aborted) logger.error(`Session subscription error: ${err}`); + } + }); + + const done = new Promise((resolve) => sub.add(() => resolve())); + await Promise.race([onAbort(signal), done]); + sub.unsubscribe(); + + logger.info("Submitter stopped"); +} + +/** + * Submits the validator set for a single target era. + * Logs success or failure internally. + */ +async function submitForEra( + clients: SubmitterClients, + config: SubmitterConfig, + targetEra: bigint, + signal: AbortSignal +): Promise { + const { publicClient, walletClient } = clients; + + const totalFee = config.executionFee + config.relayerFee; + logger.info( + `Submitting era ${targetEra} (execFee=${config.executionFee} relayerFee=${config.relayerFee})` + ); + + if (config.dryRun) { + const message = await publicClient.readContract({ + address: config.serviceManagerAddress, + abi: dataHavenServiceManagerAbi, + functionName: "buildNewValidatorSetMessageForEra", + args: [targetEra] + }); + logger.info(`[DRY RUN] Would send message: ${message}`); + return true; + } + + try { + const hash = await walletClient.writeContract({ + address: config.serviceManagerAddress, + abi: dataHavenServiceManagerAbi, + functionName: "sendNewValidatorSetForEra", + args: [targetEra, config.executionFee, config.relayerFee], + value: totalFee, + chain: null + }); + logger.info(`Transaction sent: ${hash}`); + + const receipt = await waitForReceiptWithAbort(publicClient, hash, signal); + if (receipt.status !== "success") { + logger.error(`Transaction reverted: ${hash}`); + return false; + } + + const hasOutbound = receipt.logs.some((log) => { + try { + const decoded = decodeEventLog({ + abi: gatewayAbi, + data: log.data, + topics: log.topics + }); + return decoded.eventName === "OutboundMessageAccepted"; + } catch { + return false; + } + }); + + if (!hasOutbound) { + logger.warn("Transaction succeeded but no OutboundMessageAccepted event found"); + return false; + } + + logger.info("OutboundMessageAccepted confirmed"); + return true; + } catch (err: unknown) { + if (signal.aborted) return false; + logger.error(`Submission attempt failed: ${err}`); + return false; + } +} diff --git a/test/tsconfig.json b/test/tsconfig.json index eb6e8a8d..77329677 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -43,6 +43,7 @@ "cli/**/*.ts", "wagmi.config.ts", "contract-bindings/*.ts", - "launcher/**/*.ts" + "launcher/**/*.ts", + "tools/**/*.ts" ] } diff --git a/test/utils/contracts.ts b/test/utils/contracts.ts index 48803aee..cc55dee8 100644 --- a/test/utils/contracts.ts +++ b/test/utils/contracts.ts @@ -39,22 +39,27 @@ const DeploymentsSchema = z.object({ export type Deployments = z.infer; -export const parseDeploymentsFile = async (network = "anvil"): Promise => { - const deploymentsPath = `../contracts/deployments/${network}.json`; +/** + * Parses the deployments file for a given network + * @param networkId - The network identifier (e.g., "anvil", "hoodi", "stagenet-hoodi") + * This can include an environment prefix like "stagenet-" or "testnet-" + */ +export const parseDeploymentsFile = async (networkId = "anvil"): Promise => { + const deploymentsPath = `../contracts/deployments/${networkId}.json`; const deploymentsFile = Bun.file(deploymentsPath); if (!(await deploymentsFile.exists())) { logger.error(`File ${deploymentsPath} does not exist`); - throw new Error(`Error reading ${network} deployments file`); + throw new Error(`Error reading ${networkId} deployments file`); } const deploymentsJson = await deploymentsFile.json(); logger.info(`Deployments: ${JSON.stringify(deploymentsJson, null, 2)}`); try { const parsedDeployments = DeploymentsSchema.parse(deploymentsJson); - logger.debug(`Successfully parsed ${network} deployments file.`); + logger.debug(`Successfully parsed ${networkId} deployments file.`); return parsedDeployments; } catch (error) { - logger.error(`Failed to parse ${network} deployments file:`, error); - throw new Error(`Invalid ${network} deployments file format`); + logger.error(`Failed to parse ${networkId} deployments file:`, error); + throw new Error(`Invalid ${networkId} deployments file format`); } };